summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/transferserver.cpp12
1 files changed, 9 insertions, 3 deletions
diff --git a/core/launcher/transferserver.cpp b/core/launcher/transferserver.cpp
index 28b7b49..9d18b7b 100644
--- a/core/launcher/transferserver.cpp
+++ b/core/launcher/transferserver.cpp
@@ -1,369 +1,375 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20#define _XOPEN_SOURCE 20#define _XOPEN_SOURCE
21#include <pwd.h> 21#include <pwd.h>
22#include <sys/types.h> 22#include <sys/types.h>
23#include <unistd.h> 23#include <unistd.h>
24#include <stdlib.h> 24#include <stdlib.h>
25#include <time.h> 25#include <time.h>
26#include <shadow.h> 26#include <shadow.h>
27 27
28extern "C" { 28extern "C" {
29#include <uuid/uuid.h> 29#include <uuid/uuid.h>
30#define UUID_H_INCLUDED 30#define UUID_H_INCLUDED
31} 31}
32 32
33#if defined(_OS_LINUX_) 33#if defined(_OS_LINUX_)
34#include <shadow.h> 34#include <shadow.h>
35#endif 35#endif
36 36
37#include <qdir.h> 37#include <qdir.h>
38#include <qfile.h> 38#include <qfile.h>
39#include <qtextstream.h> 39#include <qtextstream.h>
40#include <qdatastream.h> 40#include <qdatastream.h>
41#include <qmessagebox.h> 41#include <qmessagebox.h>
42#include <qstringlist.h> 42#include <qstringlist.h>
43#include <qfileinfo.h> 43#include <qfileinfo.h>
44#include <qregexp.h> 44#include <qregexp.h>
45//#include <qpe/qcopchannel_qws.h> 45//#include <qpe/qcopchannel_qws.h>
46#include <qpe/process.h> 46#include <qpe/process.h>
47#include <qpe/global.h> 47#include <qpe/global.h>
48#include <qpe/config.h> 48#include <qpe/config.h>
49#include <qpe/contact.h> 49#include <qpe/contact.h>
50#include <qpe/quuid.h> 50#include <qpe/quuid.h>
51#include <qpe/version.h> 51#include <qpe/version.h>
52#ifdef QWS 52#ifdef QWS
53#include <qpe/qcopenvelope_qws.h> 53#include <qpe/qcopenvelope_qws.h>
54#endif 54#endif
55 55
56#include "transferserver.h" 56#include "transferserver.h"
57#include "qprocess.h" 57#include "qprocess.h"
58 58
59const int block_size = 51200; 59const int block_size = 51200;
60 60
61TransferServer::TransferServer( Q_UINT16 port, QObject *parent , 61TransferServer::TransferServer( Q_UINT16 port, QObject *parent ,
62 const char* name ) 62 const char* name )
63 : QServerSocket( port, 1, parent, name ) 63 : QServerSocket( port, 1, parent, name )
64{ 64{
65 if ( !ok() ) 65 if ( !ok() )
66 qWarning( "Failed to bind to port %d", port ); 66 qWarning( "Failed to bind to port %d", port );
67} 67}
68 68
69TransferServer::~TransferServer() 69TransferServer::~TransferServer()
70{ 70{
71 71
72} 72}
73 73
74void TransferServer::newConnection( int socket ) 74void TransferServer::newConnection( int socket )
75{ 75{
76 (void) new ServerPI( socket, this ); 76 (void) new ServerPI( socket, this );
77} 77}
78 78
79QString SyncAuthentication::serverId() 79QString SyncAuthentication::serverId()
80{ 80{
81 Config cfg("Security"); 81 Config cfg("Security");
82 cfg.setGroup("Sync"); 82 cfg.setGroup("Sync");
83 QString r=cfg.readEntry("serverid"); 83 QString r=cfg.readEntry("serverid");
84 if ( r.isEmpty() ) { 84 if ( r.isEmpty() ) {
85 uuid_t uuid; 85 uuid_t uuid;
86 uuid_generate( uuid ); 86 uuid_generate( uuid );
87 cfg.writeEntry("serverid",(r = QUuid( uuid ).toString())); 87 cfg.writeEntry("serverid",(r = QUuid( uuid ).toString()));
88 } 88 }
89 return r; 89 return r;
90} 90}
91 91
92QString SyncAuthentication::ownerName() 92QString SyncAuthentication::ownerName()
93{ 93{
94 QString vfilename = Global::applicationFileName("addressbook", 94 QString vfilename = Global::applicationFileName("addressbook",
95 "businesscard.vcf"); 95 "businesscard.vcf");
96 if (QFile::exists(vfilename)) { 96 if (QFile::exists(vfilename)) {
97 Contact c; 97 Contact c;
98 c = Contact::readVCard( vfilename )[0]; 98 c = Contact::readVCard( vfilename )[0];
99 return c.fullName(); 99 return c.fullName();
100 } 100 }
101 101
102 return ""; 102 return "";
103} 103}
104 104
105QString SyncAuthentication::loginName() 105QString SyncAuthentication::loginName()
106{ 106{
107 struct passwd *pw; 107 struct passwd *pw;
108 pw = getpwuid( geteuid() ); 108 pw = getpwuid( geteuid() );
109 return QString::fromLocal8Bit( pw->pw_name ); 109 return QString::fromLocal8Bit( pw->pw_name );
110} 110}
111 111
112int SyncAuthentication::isAuthorized(QHostAddress peeraddress) 112int SyncAuthentication::isAuthorized(QHostAddress peeraddress)
113{ 113{
114 Config cfg("Security"); 114 Config cfg("Security");
115 cfg.setGroup("Sync"); 115 cfg.setGroup("Sync");
116// QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0"); 116// QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0");
117 uint auth_peer = cfg.readNumEntry("auth_peer",0xc0a80100); 117 uint auth_peer = cfg.readNumEntry("auth_peer",0xc0a80100);
118 118
119// QHostAddress allowed; 119// QHostAddress allowed;
120// allowed.setAddress(allowedstr); 120// allowed.setAddress(allowedstr);
121// uint auth_peer = allowed.ip4Addr(); 121// uint auth_peer = allowed.ip4Addr();
122 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits",24); 122 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits",24);
123 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined 123 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined
124 ? 0xffffffff : (((1<<auth_peer_bits)-1)<<(32-auth_peer_bits)); 124 ? 0xffffffff : (((1<<auth_peer_bits)-1)<<(32-auth_peer_bits));
125 return (peeraddress.ip4Addr() & mask) == auth_peer; 125 return (peeraddress.ip4Addr() & mask) == auth_peer;
126} 126}
127 127
128bool SyncAuthentication::checkUser( const QString& user ) 128bool SyncAuthentication::checkUser( const QString& user )
129{ 129{
130 if ( user.isEmpty() ) return FALSE; 130 if ( user.isEmpty() ) return FALSE;
131 QString euser = loginName(); 131 QString euser = loginName();
132 return user == euser; 132 return user == euser;
133} 133}
134 134
135bool SyncAuthentication::checkPassword( const QString& password ) 135bool SyncAuthentication::checkPassword( const QString& password )
136{ 136{
137#ifdef ALLOW_UNIX_USER_FTP 137#ifdef ALLOW_UNIX_USER_FTP
138 // First, check system password... 138 // First, check system password...
139 139
140 struct passwd *pw = 0; 140 struct passwd *pw = 0;
141 struct spwd *spw = 0; 141 struct spwd *spw = 0;
142 142
143 pw = getpwuid( geteuid() ); 143 pw = getpwuid( geteuid() );
144 spw = getspnam( pw->pw_name ); 144 spw = getspnam( pw->pw_name );
145 145
146 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd ); 146 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd );
147 if ( cpwd == "x" && spw ) 147 if ( cpwd == "x" && spw )
148 cpwd = QString::fromLocal8Bit( spw->sp_pwdp ); 148 cpwd = QString::fromLocal8Bit( spw->sp_pwdp );
149 149
150 // Note: some systems use more than crypt for passwords. 150 // Note: some systems use more than crypt for passwords.
151 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) ); 151 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) );
152 if ( cpwd == cpassword ) 152 if ( cpwd == cpassword )
153 return TRUE; 153 return TRUE;
154#endif 154#endif
155 155
156 static int lastdenial=0; 156 static int lastdenial=0;
157 static int denials=0; 157 static int denials=0;
158 int now = time(0); 158 int now = time(0);
159 159
160 // Detect old Qtopia Desktop (no password) 160 // Detect old Qtopia Desktop (no password)
161 if ( password.isEmpty() ) { 161 if ( password.isEmpty() ) {
162 if ( denials < 1 || now > lastdenial+600 ) { 162 if ( denials < 1 || now > lastdenial+600 ) {
163 QMessageBox::warning( 0,tr("Sync Connection"), 163 QMessageBox::warning( 0,tr("Sync Connection"),
164 tr("<p>An unauthorized system is requesting access to this device." 164 tr("<p>An unauthorized system is requesting access to this device."
165 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, " 165 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, "
166 "please upgrade."), 166 "please upgrade."),
167 tr("Deny") ); 167 tr("Deny") );
168 denials++; 168 denials++;
169 lastdenial=now; 169 lastdenial=now;
170 } 170 }
171 return FALSE; 171 return FALSE;
172 } 172 }
173 173
174 // Second, check sync password... 174 // Second, check sync password...
175 if ( password.left(6) == "rootme" ) { 175 QString pass = password.left(6);
176 // fuckin TT gave us the wrong sync password. 176 /* old QtopiaDesktops are sending
177 // what a dumbassed password is rootme anyway. 177 * rootme newer versions got a Qtopia
178 * prefixed. Qtopia prefix will suceed
179 * until the sync software syncs up
180 * FIXME
181 */
182 if ( pass == "rootme" || pass == "Qtopia") {
183
178 QString cpassword = QString::fromLocal8Bit( crypt( password.mid(8).local8Bit(), "qp" ) ); 184 QString cpassword = QString::fromLocal8Bit( crypt( password.mid(8).local8Bit(), "qp" ) );
179 Config cfg("Security"); 185 Config cfg("Security");
180 cfg.setGroup("Sync"); 186 cfg.setGroup("Sync");
181 QString pwds = cfg.readEntry("Passwords"); 187 QString pwds = cfg.readEntry("Passwords");
182 if ( QStringList::split(QChar(' '),pwds).contains(cpassword) ) 188 if ( QStringList::split(QChar(' '),pwds).contains(cpassword) )
183 return TRUE; 189 return TRUE;
184 190
185 // Unrecognized system. Be careful... 191 // Unrecognized system. Be careful...
186 192
187 if ( (denials > 2 && now < lastdenial+600) 193 if ( (denials > 2 && now < lastdenial+600)
188 || QMessageBox::warning(0,tr("Sync Connection"), 194 || QMessageBox::warning(0,tr("Sync Connection"),
189 tr("<p>An unrecognized system is requesting access to this device." 195 tr("<p>An unrecognized system is requesting access to this device."
190 "<p>If you have just initiated a Sync for the first time, this is normal."), 196 "<p>If you have just initiated a Sync for the first time, this is normal."),
191 tr("Allow"),tr("Deny"))==1 ) 197 tr("Allow"),tr("Deny"))==1 )
192 { 198 {
193 denials++; 199 denials++;
194 lastdenial=now; 200 lastdenial=now;
195 return FALSE; 201 return FALSE;
196 } else { 202 } else {
197 denials=0; 203 denials=0;
198 cfg.writeEntry("Passwords",pwds+" "+cpassword); 204 cfg.writeEntry("Passwords",pwds+" "+cpassword);
199 return TRUE; 205 return TRUE;
200 } 206 }
201 } 207 }
202 208
203 return FALSE; 209 return FALSE;
204} 210}
205 211
206ServerPI::ServerPI( int socket, QObject *parent , const char* name ) 212ServerPI::ServerPI( int socket, QObject *parent , const char* name )
207 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ) 213 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 )
208{ 214{
209 state = Connected; 215 state = Connected;
210 216
211 setSocket( socket ); 217 setSocket( socket );
212 218
213 peerport = peerPort(); 219 peerport = peerPort();
214 peeraddress = peerAddress(); 220 peeraddress = peerAddress();
215 221
216#ifndef INSECURE 222#ifndef INSECURE
217 if ( !SyncAuthentication::isAuthorized(peeraddress) ) { 223 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
218 state = Forbidden; 224 state = Forbidden;
219 startTimer( 0 ); 225 startTimer( 0 );
220 } else 226 } else
221#endif 227#endif
222 { 228 {
223 connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); 229 connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
224 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); 230 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
225 231
226 passiv = FALSE; 232 passiv = FALSE;
227 for( int i = 0; i < 4; i++ ) 233 for( int i = 0; i < 4; i++ )
228 wait[i] = FALSE; 234 wait[i] = FALSE;
229 235
230 send( "220 Qtopia " QPE_VERSION " FTP Server" ); 236 send( "220 Qtopia " QPE_VERSION " FTP Server" );
231 state = Wait_USER; 237 state = Wait_USER;
232 238
233 dtp = new ServerDTP( this ); 239 dtp = new ServerDTP( this );
234 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) ); 240 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) );
235 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) ); 241 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) );
236 connect( dtp, SIGNAL( error( int ) ), SLOT( dtpError( int ) ) ); 242 connect( dtp, SIGNAL( error( int ) ), SLOT( dtpError( int ) ) );
237 243
238 244
239 directory = QDir::currentDirPath(); 245 directory = QDir::currentDirPath();
240 246
241 static int p = 1024; 247 static int p = 1024;
242 248
243 while ( !serversocket || !serversocket->ok() ) { 249 while ( !serversocket || !serversocket->ok() ) {
244 delete serversocket; 250 delete serversocket;
245 serversocket = new ServerSocket( ++p, this ); 251 serversocket = new ServerSocket( ++p, this );
246 } 252 }
247 connect( serversocket, SIGNAL( newIncomming( int ) ), 253 connect( serversocket, SIGNAL( newIncomming( int ) ),
248 SLOT( newConnection( int ) ) ); 254 SLOT( newConnection( int ) ) );
249 } 255 }
250} 256}
251 257
252ServerPI::~ServerPI() 258ServerPI::~ServerPI()
253{ 259{
254 260
255} 261}
256 262
257void ServerPI::connectionClosed() 263void ServerPI::connectionClosed()
258{ 264{
259 // qDebug( "Debug: Connection closed" ); 265 // qDebug( "Debug: Connection closed" );
260 delete this; 266 delete this;
261} 267}
262 268
263void ServerPI::send( const QString& msg ) 269void ServerPI::send( const QString& msg )
264{ 270{
265 QTextStream os( this ); 271 QTextStream os( this );
266 os << msg << endl; 272 os << msg << endl;
267 //qDebug( "Reply: %s", msg.latin1() ); 273 //qDebug( "Reply: %s", msg.latin1() );
268} 274}
269 275
270void ServerPI::read() 276void ServerPI::read()
271{ 277{
272 while ( canReadLine() ) 278 while ( canReadLine() )
273 process( readLine().stripWhiteSpace() ); 279 process( readLine().stripWhiteSpace() );
274} 280}
275 281
276bool ServerPI::checkReadFile( const QString& file ) 282bool ServerPI::checkReadFile( const QString& file )
277{ 283{
278 QString filename; 284 QString filename;
279 285
280 if ( file[0] != "/" ) 286 if ( file[0] != "/" )
281 filename = directory.path() + "/" + file; 287 filename = directory.path() + "/" + file;
282 else 288 else
283 filename = file; 289 filename = file;
284 290
285 QFileInfo fi( filename ); 291 QFileInfo fi( filename );
286 return ( fi.exists() && fi.isReadable() ); 292 return ( fi.exists() && fi.isReadable() );
287} 293}
288 294
289bool ServerPI::checkWriteFile( const QString& file ) 295bool ServerPI::checkWriteFile( const QString& file )
290{ 296{
291 QString filename; 297 QString filename;
292 298
293 if ( file[0] != "/" ) 299 if ( file[0] != "/" )
294 filename = directory.path() + "/" + file; 300 filename = directory.path() + "/" + file;
295 else 301 else
296 filename = file; 302 filename = file;
297 303
298 QFileInfo fi( filename ); 304 QFileInfo fi( filename );
299 305
300 if ( fi.exists() ) 306 if ( fi.exists() )
301 if ( !QFile( filename ).remove() ) 307 if ( !QFile( filename ).remove() )
302 return FALSE; 308 return FALSE;
303 return TRUE; 309 return TRUE;
304} 310}
305 311
306void ServerPI::process( const QString& message ) 312void ServerPI::process( const QString& message )
307{ 313{
308 //qDebug( "Command: %s", message.latin1() ); 314 //qDebug( "Command: %s", message.latin1() );
309 315
310 // split message using "," as separator 316 // split message using "," as separator
311 QStringList msg = QStringList::split( " ", message ); 317 QStringList msg = QStringList::split( " ", message );
312 if ( msg.isEmpty() ) return; 318 if ( msg.isEmpty() ) return;
313 319
314 // command token 320 // command token
315 QString cmd = msg[0].upper(); 321 QString cmd = msg[0].upper();
316 322
317 // argument token 323 // argument token
318 QString arg; 324 QString arg;
319 if ( msg.count() >= 2 ) 325 if ( msg.count() >= 2 )
320 arg = msg[1]; 326 arg = msg[1];
321 327
322 // full argument string 328 // full argument string
323 QString args; 329 QString args;
324 if ( msg.count() >= 2 ) { 330 if ( msg.count() >= 2 ) {
325 QStringList copy( msg ); 331 QStringList copy( msg );
326 // FIXME: for Qt3 332 // FIXME: for Qt3
327 // copy.pop_front() 333 // copy.pop_front()
328 copy.remove( copy.begin() ); 334 copy.remove( copy.begin() );
329 args = copy.join( " " ); 335 args = copy.join( " " );
330 } 336 }
331 337
332 //qDebug( "args: %s", args.latin1() ); 338 //qDebug( "args: %s", args.latin1() );
333 339
334 // we always respond to QUIT, regardless of state 340 // we always respond to QUIT, regardless of state
335 if ( cmd == "QUIT" ) { 341 if ( cmd == "QUIT" ) {
336 send( "211 Good bye!" ); 342 send( "211 Good bye!" );
337 delete this; 343 delete this;
338 return; 344 return;
339 } 345 }
340 346
341 // connected to client 347 // connected to client
342 if ( Connected == state ) 348 if ( Connected == state )
343 return; 349 return;
344 350
345 // waiting for user name 351 // waiting for user name
346 if ( Wait_USER == state ) { 352 if ( Wait_USER == state ) {
347 353
348 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) { 354 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
349 send( "530 Please login with USER and PASS" ); 355 send( "530 Please login with USER and PASS" );
350 return; 356 return;
351 } 357 }
352 send( "331 User name ok, need password" ); 358 send( "331 User name ok, need password" );
353 state = Wait_PASS; 359 state = Wait_PASS;
354 return; 360 return;
355 } 361 }
356 362
357 // waiting for password 363 // waiting for password
358 if ( Wait_PASS == state ) { 364 if ( Wait_PASS == state ) {
359 365
360 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) { 366 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
361 send( "530 Please login with USER and PASS" ); 367 send( "530 Please login with USER and PASS" );
362 return; 368 return;
363 } 369 }
364 send( "230 User logged in, proceed" ); 370 send( "230 User logged in, proceed" );
365 state = Ready; 371 state = Ready;
366 return; 372 return;
367 } 373 }
368 374
369 // ACCESS CONTROL COMMANDS 375 // ACCESS CONTROL COMMANDS