Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

krfblogin.cpp

Go to the documentation of this file.
00001 #include "krfblogin.h"
00002 #include "krfbconnection.h"
00003 
00004 /* OPIE */
00005 #include <opie2/odebug.h>
00006 using namespace Opie::Core;
00007 
00008 /* QT */
00009 #include <qtimer.h>
00010 
00011 /* STD */
00012 #include <assert.h>
00013 extern "C" {
00014 #include "vncauth.h"
00015 }
00016 
00017 // The length of the various messages (used to decide how many bytes to
00018 // wait for).
00019 const int ServerVersionLength = 12;
00020 const int ClientVersionLength = 12;
00021 const int AuthSchemeLength = 4;
00022 const int FailureReasonSizeLength = 4;
00023 const int ChallengeLength = 16;
00024 const int AuthResultLength = 4;
00025 
00026 // Authentication results
00027 enum AuthResult {
00028   AuthOk,
00029   AuthFailed,
00030   AuthTooMany
00031 };
00032 
00033 typedef unsigned char CARD8;
00034 typedef unsigned short CARD16;
00035 typedef unsigned long CARD32;
00036 
00037 const int endianTest = 1;
00038 
00039 // Endian stuff
00040 #define Swap16IfLE(s) \
00041     (*(char *)&endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s))
00042 
00043 #define Swap32IfLE(l) \
00044     (*(char *)&endianTest ? ((((l) & 0xff000000) >> 24) | \
00045                              (((l) & 0x00ff0000) >> 8)  | \
00046                              (((l) & 0x0000ff00) << 8)  | \
00047                              (((l) & 0x000000ff) << 24))  : (l))
00048 
00049 KRFBLogin::KRFBLogin( KRFBConnection *con )
00050   : QObject( con, "RFB login manager" )
00051 {
00052   assert( con );
00053   this->con = con;
00054   currentState = AwaitingServerVersion;
00055 
00056   connect( this, SIGNAL( error(const QString&) ),
00057            con, SIGNAL( error(const QString&) ) );
00058 
00059 
00060   owarn << "Waiting for server version..." << oendl; 
00061 
00062   static QString statusMsg = tr( "Waiting for server version..." );
00063   emit status( statusMsg );
00064 
00065   // Kick off the state machine
00066   connect( con, SIGNAL( gotEnoughData() ), SLOT( gotServerVersion() ) );
00067   con->waitForData( ServerVersionLength );
00068 }
00069 
00070 KRFBLogin::~KRFBLogin()
00071 {
00072 
00073 }
00074 
00075 KRFBLogin::State KRFBLogin::state() const
00076 {
00077   return currentState;
00078 }
00079 
00080 void KRFBLogin::gotServerVersion()
00081 {
00082   owarn << "Got server version" << oendl; 
00083 
00084   disconnect( con, SIGNAL( gotEnoughData() ), 
00085               this, SLOT( gotServerVersion() ) );
00086 
00087   // Read the server's version message
00088   char serverVersion[ ServerVersionLength + 1 ];
00089   con->read( serverVersion, ServerVersionLength );
00090   serverVersion[ ServerVersionLength ] = '\0';
00091 
00092   QCString rfbString( serverVersion, ServerVersionLength + 1 );
00093   versionString = rfbString;
00094 
00095   QRegExp regexp( "RFB [0-9][0-9][0-9]\\.[0-9][0-9][0-9]\n" );
00096 
00097   if ( rfbString.find( regexp ) == -1 ) {
00098     static QString msg = tr( "Error: Invalid server version, %1" ).arg( rfbString );
00099 
00100     owarn << msg << oendl; 
00101     emit error( msg );
00102     currentState = Error;
00103     return;
00104   }
00105 
00106   // Calculate the actual version number
00107   serverMajor = (serverVersion[4] - '0') * 100
00108     + (serverVersion[5] - '0') * 10
00109     + (serverVersion[6] - '0');
00110   serverMinor = (serverVersion[8] - '0') * 100
00111     + (serverVersion[9] - '0') * 10
00112     + (serverVersion[10] - '0');
00113 
00114   owarn << "Server Version: " << serverMajor << "." << serverMinor << "" << oendl; 
00115 
00116   if ( serverMajor != 3 ) {
00117     QString msg = tr( "Error: Unsupported server version, %1" )
00118       .arg( rfbString );
00119 
00120     owarn << msg << oendl; 
00121     emit error( msg );
00122     currentState = Error;
00123     return;    
00124   }
00125   
00126   if ( serverMinor != 3 ) {
00127     owarn << "Minor version mismatch: " << serverMinor << "" << oendl; 
00128   }
00129 
00130   // Setup for the next state
00131   sendClientVersion();
00132 
00133   connect( con, SIGNAL( gotEnoughData() ), SLOT( gotAuthScheme() ) );
00134   con->waitForData( AuthSchemeLength );
00135 }
00136 
00137 void KRFBLogin::gotAuthScheme()
00138 {
00139   disconnect( con, SIGNAL( gotEnoughData() ), 
00140               this, SLOT( gotAuthScheme() ) );
00141 
00142   // Got data
00143   CARD32 scheme;
00144   con->read( &scheme, AuthSchemeLength );
00145   scheme = Swap32IfLE( scheme );
00146 
00147   static QString statusMsgOk = tr( "Logged in" );
00148 
00149   switch ( scheme ) {
00150   case 0:
00151     owarn << "Failed" << oendl; 
00152     // Handle failure
00153     connect( con, SIGNAL( gotEnoughData() ), SLOT( gotFailureReasonSize() ) );
00154     con->waitForData( FailureReasonSizeLength );
00155     break;
00156   case 1:
00157     // Handle no auth
00158     emit status( statusMsgOk );
00159     con->gotRFBConnection();
00160     break;
00161   case 2:
00162     // Handle VNC auth
00163     connect( con, SIGNAL( gotEnoughData() ), SLOT( gotChallenge() ) );
00164     con->waitForData( ChallengeLength );
00165     break;
00166   default:
00167     owarn << "Unknown authentication scheme, 0x" << scheme << "" << oendl; 
00168     currentState = Error;
00169     break;
00170   };
00171 }
00172 
00173 void KRFBLogin::gotChallenge()
00174 {
00175   disconnect( con, SIGNAL( gotEnoughData() ),
00176               this, SLOT( gotChallenge() ) );
00177 
00178   QTimer::singleShot( 0, this, SLOT(getPassword()) );
00179 }
00180 
00181 void KRFBLogin::getPassword()
00182 {
00183   // Got data
00184   CARD8 challenge[ ChallengeLength ];
00185   con->read( challenge, ChallengeLength );
00186 
00187   // Last chance to enter a password
00188   if ( con->options_->password.isNull() ) {
00189     owarn << "krfblogin needs a password" << oendl; 
00190     emit passwordRequired( con );
00191   }
00192 
00193   if ( con->options_->password.isNull() ) {
00194     QString msg = tr( "Error: This server requires a password, but none "
00195                         "has been specified.\n" );
00196     
00197     emit error( msg );
00198     return;
00199   }
00200 
00201   vncEncryptBytes( (unsigned char *) challenge, QCString(con->options_->password.latin1()).data() );
00202   con->write( challenge, ChallengeLength );
00203 
00204   connect( con, SIGNAL( gotEnoughData() ), SLOT( gotAuthResult() ) );
00205   con->waitForData( AuthResultLength );
00206 }
00207 
00208 void KRFBLogin::gotFailureReasonSize()
00209 {
00210   disconnect( con, SIGNAL( gotEnoughData() ), this,
00211               SLOT( gotFailureReasonSize() ) );
00212 }
00213 
00214 void KRFBLogin::gotAuthResult()
00215 {
00216   // Got data
00217   disconnect( con, SIGNAL( gotEnoughData() ), this,
00218               SLOT( gotAuthResult() ) );
00219 
00220   long result;
00221   con->read( &result, AuthResultLength );
00222   result = Swap32IfLE( result );
00223 
00224   owarn << "Authentication Result is 0x" << result << "" << oendl; 
00225 
00226   static QString failed = tr( "Error: The password you specified was incorrect." );
00227   static QString tooMany = tr( "Error: Too many invalid login attempts have been made\n"
00228                                  "to this account, please try later." );
00229 
00230   static QString statusMsgOk = tr( "Logged in" );
00231   static QString statusMsgFailed = tr( "Login Failed" );
00232   static QString statusMsgTooMany = tr( "Too many failures" );
00233 
00234   switch( result ) {
00235   case AuthOk:
00236     emit status( statusMsgOk );
00237     con->gotRFBConnection();
00238     break;
00239   case AuthFailed:
00240     owarn << "Dammit" << oendl; 
00241     emit status( statusMsgFailed );
00242     emit error( failed );
00243     break;
00244   case AuthTooMany:
00245     emit status( statusMsgTooMany );
00246     emit error( tooMany );    
00247     break;
00248   default:
00249     owarn << "Invalid authentication result, " << result << "" << oendl; 
00250     break;
00251   }
00252 }
00253 
00254 void KRFBLogin::sendClientVersion()
00255 {
00256   owarn << "Sending client version" << oendl; 
00257   con->write( (void*)"RFB 003.003\n", ClientVersionLength );
00258 }

Generated on Sat Nov 5 16:17:16 2005 for OPIE by  doxygen 1.4.2