summaryrefslogtreecommitdiff
path: root/noncore/comm/keypebble/krfblogin.cpp
authorkergoth <kergoth>2002-01-25 22:14:26 (UTC)
committer kergoth <kergoth>2002-01-25 22:14:26 (UTC)
commit15318cad33835e4e2dc620d033e43cd930676cdd (patch) (unidiff)
treec2fa0399a2c47fda8e2cd0092c73a809d17f68eb /noncore/comm/keypebble/krfblogin.cpp
downloadopie-15318cad33835e4e2dc620d033e43cd930676cdd.zip
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.gz
opie-15318cad33835e4e2dc620d033e43cd930676cdd.tar.bz2
Initial revision
Diffstat (limited to 'noncore/comm/keypebble/krfblogin.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/comm/keypebble/krfblogin.cpp255
1 files changed, 255 insertions, 0 deletions
diff --git a/noncore/comm/keypebble/krfblogin.cpp b/noncore/comm/keypebble/krfblogin.cpp
new file mode 100644
index 0000000..073ba0e
--- a/dev/null
+++ b/noncore/comm/keypebble/krfblogin.cpp
@@ -0,0 +1,255 @@
1#include <assert.h>
2
3
4extern "C" {
5#include "vncauth.h"
6}
7
8#include "krfblogin.h"
9#include "krfbconnection.h"
10#include <qtimer.h>
11
12// The length of the various messages (used to decide how many bytes to
13// wait for).
14const int ServerVersionLength = 12;
15const int ClientVersionLength = 12;
16const int AuthSchemeLength = 4;
17const int FailureReasonSizeLength = 4;
18const int ChallengeLength = 16;
19const int AuthResultLength = 4;
20
21// Authentication results
22enum AuthResult {
23 AuthOk,
24 AuthFailed,
25 AuthTooMany
26};
27
28typedef unsigned char CARD8;
29typedef unsigned short CARD16;
30typedef unsigned long CARD32;
31
32const int endianTest = 1;
33
34// Endian stuff
35#define Swap16IfLE(s) \
36 (*(char *)&endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s))
37
38#define Swap32IfLE(l) \
39 (*(char *)&endianTest ? ((((l) & 0xff000000) >> 24) | \
40 (((l) & 0x00ff0000) >> 8) | \
41 (((l) & 0x0000ff00) << 8) | \
42 (((l) & 0x000000ff) << 24)) : (l))
43
44KRFBLogin::KRFBLogin( KRFBConnection *con )
45 : QObject( con, "RFB login manager" )
46{
47 assert( con );
48 this->con = con;
49 currentState = AwaitingServerVersion;
50
51 connect( this, SIGNAL( error( const QString & ) ),
52 con, SIGNAL( error( const QString & ) ) );
53
54 connect( this, SIGNAL( passwordRequired( KRFBConnection * ) ),
55 con, SIGNAL( passwordRequired( KRFBConnection * ) ) );
56
57 qWarning( "Waiting for server version..." );
58
59 static QString statusMsg = tr( "Waiting for server version..." );
60 emit status( statusMsg );
61
62 // Kick off the state machine
63 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerVersion() ) );
64 con->waitForData( ServerVersionLength );
65}
66
67KRFBLogin::~KRFBLogin()
68{
69
70}
71
72KRFBLogin::State KRFBLogin::state() const
73{
74 return currentState;
75}
76
77void KRFBLogin::gotServerVersion()
78{
79 qWarning( "Got server version" );
80
81 disconnect( con, SIGNAL( gotEnoughData() ),
82 this, SLOT( gotServerVersion() ) );
83
84 // Read the server's version message
85 char serverVersion[ ServerVersionLength + 1 ];
86 con->read( serverVersion, ServerVersionLength );
87 serverVersion[ ServerVersionLength ] = '\0';
88
89 QCString rfbString( serverVersion, ServerVersionLength + 1 );
90 versionString = rfbString;
91
92 QRegExp regexp( "RFB [0-9][0-9][0-9]\\.[0-9][0-9][0-9]\n" );
93
94 if ( rfbString.find( regexp ) == -1 ) {
95 static QString msg = tr( "Error: Invalid server version, %1" ).arg( rfbString );
96
97 qWarning( msg );
98 emit error( msg );
99 currentState = Error;
100 return;
101 }
102
103 // Calculate the actual version number
104 serverMajor = (serverVersion[4] - '0') * 100
105 + (serverVersion[5] - '0') * 10
106 + (serverVersion[6] - '0');
107 serverMinor = (serverVersion[8] - '0') * 100
108 + (serverVersion[9] - '0') * 10
109 + (serverVersion[10] - '0');
110
111 qWarning("Server Version: %03d.%03d", serverMajor, serverMinor );
112
113 if ( serverMajor != 3 ) {
114 QString msg = tr( "Error: Unsupported server version, %1" )
115 .arg( rfbString );
116
117 qWarning( msg );
118 emit error( msg );
119 currentState = Error;
120 return;
121 }
122
123 if ( serverMinor != 3 ) {
124 qWarning( "Minor version mismatch: %d", serverMinor );
125 }
126
127 // Setup for the next state
128 sendClientVersion();
129
130 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotAuthScheme() ) );
131 con->waitForData( AuthSchemeLength );
132}
133
134void KRFBLogin::gotAuthScheme()
135{
136 disconnect( con, SIGNAL( gotEnoughData() ),
137 this, SLOT( gotAuthScheme() ) );
138
139 // Got data
140 CARD32 scheme;
141 con->read( &scheme, AuthSchemeLength );
142 scheme = Swap32IfLE( scheme );
143
144 static QString statusMsgOk = tr( "Logged in" );
145
146 switch ( scheme ) {
147 case 0:
148 qWarning( "Failed" );
149 // Handle failure
150 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotFailureReasonSize() ) );
151 con->waitForData( FailureReasonSizeLength );
152 break;
153 case 1:
154 // Handle no auth
155 emit status( statusMsgOk );
156 con->gotRFBConnection();
157 break;
158 case 2:
159 // Handle VNC auth
160 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotChallenge() ) );
161 con->waitForData( ChallengeLength );
162 break;
163 default:
164 qWarning( "Unknown authentication scheme, 0x%08lx", scheme );
165 currentState = Error;
166 break;
167 };
168}
169
170void KRFBLogin::gotChallenge()
171{
172 disconnect( con, SIGNAL( gotEnoughData() ),
173 this, SLOT( gotChallenge() ) );
174
175 QTimer::singleShot( 0, this, SLOT(getPassword()) );
176}
177
178void KRFBLogin::getPassword()
179{
180 // Got data
181 CARD8 challenge[ ChallengeLength ];
182 con->read( challenge, ChallengeLength );
183
184 // Last chance to enter a password
185 if ( con->pass_.isNull() ) {
186 qWarning( "krfblogin needs a password" );
187 emit passwordRequired( con );
188 }
189
190 if ( con->pass_.isNull() ) {
191 QString msg = tr( "Error: This server requires a password, but none "
192 "has been specified.\n" );
193
194 emit error( msg );
195 return;
196 }
197
198 vncEncryptBytes( (unsigned char *) challenge, con->pass_.data() );
199 con->write( challenge, ChallengeLength );
200
201 connect( con, SIGNAL( gotEnoughData() ), SLOT( gotAuthResult() ) );
202 con->waitForData( AuthResultLength );
203}
204
205void KRFBLogin::gotFailureReasonSize()
206{
207 disconnect( con, SIGNAL( gotEnoughData() ), this,
208 SLOT( gotFailureReasonSize() ) );
209}
210
211void KRFBLogin::gotAuthResult()
212{
213 // Got data
214 disconnect( con, SIGNAL( gotEnoughData() ), this,
215 SLOT( gotAuthResult() ) );
216
217 long result;
218 con->read( &result, AuthResultLength );
219 result = Swap32IfLE( result );
220
221 qWarning( "Authentication Result is 0x%08lx", result );
222
223 static QString failed = tr( "Error: The password you specified was incorrect." );
224 static QString tooMany = tr( "Error: Too many invalid login attempts have been made\n"
225 "to this account, please try later." );
226
227 static QString statusMsgOk = tr( "Logged in" );
228 static QString statusMsgFailed = tr( "Login Failed" );
229 static QString statusMsgTooMany = tr( "Too many failures" );
230
231 switch( result ) {
232 case AuthOk:
233 emit status( statusMsgOk );
234 con->gotRFBConnection();
235 break;
236 case AuthFailed:
237 qWarning( "Dammit" );
238 emit status( statusMsgFailed );
239 emit error( failed );
240 break;
241 case AuthTooMany:
242 emit status( statusMsgTooMany );
243 emit error( tooMany );
244 break;
245 default:
246 qWarning( "Invalid authentication result, %lx", result );
247 break;
248 }
249}
250
251void KRFBLogin::sendClientVersion()
252{
253 qWarning( "Sending client version" );
254 con->write( (void*)"RFB 003.003\n", ClientVersionLength );
255}