2
* ItalcVncServer.cpp - implementation of ItalcVncServer, a VNC-server-
3
* abstraction for platform independent VNC-server-usage
5
* Copyright (c) 2006-2010 Tobias Doerffel <tobydox/at/users/dot/sf/dot/net>
7
* This file is part of iTALC - http://italc.sourceforge.net
9
* This program is free software; you can redistribute it and/or
10
* modify it under the terms of the GNU General Public
11
* License as published by the Free Software Foundation; either
12
* version 2 of the License, or (at your option) any later version.
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
* General Public License for more details.
19
* You should have received a copy of the GNU General Public
20
* License along with this program (see COPYING); if not, write to the
21
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22
* Boston, MA 02111-1307, USA.
26
#include <italcconfig.h>
31
#ifdef ITALC_BUILD_WIN32
45
#include <QtCore/QCoreApplication>
46
#include <QtCore/QDir>
47
#include <QtCore/QProcess>
49
#include "ItalcVncServer.h"
50
#include "ItalcConfiguration.h"
51
#include "ItalcCore.h"
52
#include "ItalcCoreServer.h"
53
#include "ItalcRfbExt.h"
55
#include "LogonAuthentication.h"
58
extern "C" int x11vnc_main( int argc, char * * argv );
62
qint64 libvncServerDispatcher( char * _buf, const qint64 _len,
63
const SocketOpCodes _op_code, void * _user )
65
rfbClientPtr cl = (rfbClientPtr) _user;
69
return rfbReadExact( cl, _buf, _len ) == 1 ? _len : 0;
71
return rfbWriteExact( cl, _buf, _len ) == 1 ? _len : 0;
72
case SocketGetPeerAddress:
73
strncpy( _buf, cl->host, _len );
83
static rfbBool italcCoreNewClient( struct _rfbClientRec *, void * * )
91
static rfbBool lvs_italcHandleMessage( struct _rfbClientRec *client,
93
const rfbClientToServerMsg *message )
95
if( message->type == rfbItalcCoreRequest )
97
return ItalcCoreServer::instance()->
98
handleItalcClientMessage( libvncServerDispatcher, client );
104
extern "C" void rfbClientSendString(rfbClientPtr cl, char *reason);
107
static void lvs_italcSecurityHandler( struct _rfbClientRec *cl )
109
bool authOK = ItalcCoreServer::instance()->
110
authSecTypeItalc( libvncServerDispatcher, cl );
112
uint32_t result = authOK ? rfbVncAuthOK : rfbVncAuthFailed;
113
result = Swap32IfLE( result );
114
rfbWriteExact( cl, (char *) &result, 4 );
118
cl->state = rfbClientRec::RFB_INITIALISATION;
122
rfbClientSendString( cl, (char *) "Signature verification failed!" );
129
#ifndef ITALC_BUILD_WIN32
131
static void vncDecryptBytes(unsigned char *where, const int length, const unsigned char *key)
134
rfbDesKey((unsigned char*) key, DE1);
135
for (i = length - 8; i > 0; i -= 8) {
136
rfbDes(where + i, where + i);
137
for (j = 0; j < 8; j++)
138
where[i + j] ^= where[i + j - 8];
141
rfbDes(where, where);
142
for (i = 0; i < 8; i++)
148
static bool authMsLogon( struct _rfbClientRec *cl )
151
char gen[8], mod[8], pub[8], resp[8];
152
char user[256], passwd[64];
153
unsigned char key[8];
156
int64ToBytes( dh.getValue(DH_GEN), gen );
157
int64ToBytes( dh.getValue(DH_MOD), mod );
158
int64ToBytes( dh.createInterKey(), pub );
159
if( !rfbWriteExact( cl, gen, sizeof(gen) ) ) return false;
160
if( !rfbWriteExact( cl, mod, sizeof(mod) ) ) return false;
161
if( !rfbWriteExact( cl, pub, sizeof(pub) ) ) return false;
162
if( !rfbReadExact( cl, resp, sizeof(resp) ) ) return false;
163
if( !rfbReadExact( cl, user, sizeof(user) ) ) return false;
164
if( !rfbReadExact( cl, passwd, sizeof(passwd) ) ) return false;
166
int64ToBytes( dh.createEncryptionKey( bytesToInt64( resp ) ), (char*) key );
167
vncDecryptBytes( (unsigned char*) user, sizeof(user), key ); user[255] = '\0';
168
vncDecryptBytes( (unsigned char*) passwd, sizeof(passwd), key ); passwd[63] = '\0';
170
AuthenticationCredentials credentials;
171
credentials.setLogonUsername( user );
172
credentials.setLogonPassword( passwd );
174
return LogonAuthentication::authenticateUser( credentials );
179
static void lvs_msLogonIISecurityHandler( struct _rfbClientRec *cl )
181
bool authOK = authMsLogon( cl );
183
uint32_t result = authOK ? rfbVncAuthOK : rfbVncAuthFailed;
184
result = Swap32IfLE( result );
185
rfbWriteExact( cl, (char *) &result, 4 );
189
cl->state = rfbClientRec::RFB_INITIALISATION;
193
rfbClientSendString( cl, (char *) "MS Logon II authentication failed!" );
200
#ifdef ITALC_BUILD_WIN32
202
extern bool Myinit( HINSTANCE hInstance );
203
extern int WinVNCAppMain();
209
ItalcVncServer::ItalcVncServer() :
211
m_port( ItalcCore::serverPort )
217
ItalcVncServer::~ItalcVncServer()
223
static void runX11vnc( QStringList cmdline, int port, bool plainVnc )
226
<< "-nosel" // do not exchange clipboard-contents
227
<< "-nosetclipboard" // do not exchange clipboard-contents
228
<< "-rfbport" << QString::number( port )
229
// set port where the VNC server should listen
232
#ifdef ITALC_BUILD_LINUX
233
if( !plainVnc && ItalcCore::config->isHttpServerEnabled() )
235
QDir d( QCoreApplication::applicationDirPath() );
236
if( d.cdUp() && d.cd( "share" ) && d.cd( "italc" ) &&
237
d.cd( "JavaViewer" ) )
239
cmdline << "-httpport"
240
<< QString::number( ItalcCore::config->httpServerPort() )
241
<< "-httpdir" << d.absolutePath();
242
LogStream() << "Using JavaViewer files at" << d.absolutePath();
246
qWarning( "Could not find JavaViewer files. "
247
"Check your iTALC installation!" );
251
// workaround for x11vnc when running in an NX session
252
foreach( const QString &s, QProcess::systemEnvironment() )
254
if( s.startsWith( "NXSESSIONID=" ) || s.startsWith( "X2GO_SESSION=" ) )
256
cmdline << "-noxdamage";
261
// build new C-style command line array based on cmdline-QStringList
262
char **argv = new char *[cmdline.size()+1];
263
argv[0] = qstrdup( QCoreApplication::arguments()[0].toUtf8().constData() );
266
for( QStringList::iterator it = cmdline.begin();
267
it != cmdline.end(); ++it, ++argc )
269
argv[argc] = new char[it->length() + 1];
270
strcpy( argv[argc], it->toUtf8().constData() );
273
if( plainVnc == false )
275
// register iTALC protocol extension
276
rfbProtocolExtension pe;
277
pe.newClient = italcCoreNewClient;
279
pe.enablePseudoEncoding = NULL;
280
pe.pseudoEncodings = NULL;
281
pe.handleMessage = lvs_italcHandleMessage;
284
pe.processArgument = NULL;
286
rfbRegisterProtocolExtension( &pe );
289
// register handler for iTALC's security-type
290
rfbSecurityHandler shi = { rfbSecTypeItalc, lvs_italcSecurityHandler, NULL };
291
rfbRegisterSecurityHandler( &shi );
293
#ifndef ITALC_BUILD_WIN32
294
// register handler for MS Logon II security type
295
rfbSecurityHandler shmsl = { rfbUltraVNC_MsLogonIIAuth, lvs_msLogonIISecurityHandler, NULL };
296
rfbRegisterSecurityHandler( &shmsl );
298
rfbSecurityHandler shmsl_legacy = { rfbMSLogon, lvs_msLogonIISecurityHandler, NULL };
299
rfbRegisterSecurityHandler( &shmsl_legacy );
303
x11vnc_main( argc, argv );
309
void ItalcVncServer::runVncReflector( int srcPort, int dstPort )
311
#ifdef ITALC_BUILD_WIN32
312
pthread_win32_process_attach_np();
313
pthread_win32_thread_attach_np();
319
<< QString( "localhost:%1" ).arg( srcPort );
320
if( ItalcCore::config->isDemoServerMultithreaded() )
327
runX11vnc( args, dstPort, true );
330
#ifdef ITALC_BUILD_WIN32
331
pthread_win32_thread_detach_np();
332
pthread_win32_process_detach_np();
338
void ItalcVncServer::run()
340
#ifdef ITALC_BUILD_LINUX
343
QStringList acceptedArguments;
350
foreach( const QString & arg, QCoreApplication::arguments() )
352
if( acceptedArguments.contains( arg ) )
354
cmdline.append( arg );
358
runX11vnc( cmdline, m_port, false );
360
#elif ITALC_BUILD_WIN32
363
Myinit( GetModuleHandle( NULL ) );