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