00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "nAuthentication.h"
00029 #include "tMemManager.h"
00030 #include "tToDo.h"
00031 #include "tLocale.h"
00032 #include "tRecorder.h"
00033 #include "tSysTime.h"
00034
00035 #include "nNetwork.h"
00036 #include "nNetObject.h"
00037 #include "nSocket.h"
00038
00039 #include <memory>
00040 #include <string>
00041 #include <string.h>
00042
00043 #include <deque>
00044
00045 #ifdef HAVE_LIBZTHREAD
00046 #include <zthread/Thread.h>
00047 #include <zthread/LockedQueue.h>
00048
00049 #include <zthread/FastMutex.h>
00050 #include <zthread/FastRecursiveMutex.h>
00051 #include <zthread/Guard.h>
00052 #include <zthread/SynchronousExecutor.h>
00053 #include <zthread/ThreadedExecutor.h>
00054 typedef ZThread::ThreadedExecutor nExecutor;
00055
00056 typedef ZThread::FastMutex nMutex;
00057 #else
00058 typedef tNonMutex nMutex;
00059 #endif
00060
00061
00062 static tString sn_AuthorityBlacklist, sn_AuthorityWhitelist;
00063 tConfItemLine sn_AuthorityBlacklistConf( "AUTHORITY_BLACKLIST", sn_AuthorityBlacklist );
00064 tConfItemLine sn_AuthorityWhitelistConf( "AUTHORITY_WHITELIST", sn_AuthorityWhitelist );
00065
00066 #ifdef DEBUG
00067
00068 static tString sn_AuthorityNoCheck;
00069 tConfItemLine sn_AuthorityNoCheckConf( "AUTHORITY_NO_CHECK", sn_AuthorityNoCheck );
00070 #endif
00071
00072 static nAuthentication::UserPasswordCallback* S_UserPasswordCallback = NULL;
00073 static nAuthentication::LoginResultCallback* S_LoginResultCallback = NULL;
00074
00075
00076 void nAuthentication::SetUserPasswordCallback(nAuthentication::UserPasswordCallback* callback)
00077 {
00078 S_UserPasswordCallback = callback;
00079 }
00080
00081 void nAuthentication::SetLoginResultCallback (nAuthentication::LoginResultCallback* callback)
00082 {
00083 S_LoginResultCallback = callback;
00084 }
00085
00086
00087
00088 static nDescriptor nPasswordRequest(40, &nAuthentication::HandlePasswordRequest, "password_request");
00089
00090 static nDescriptor nPasswordAnswer(41, &nAuthentication::HandlePasswordAnswer, "password_answer");
00091
00092
00093 static nKrawall::nPasswordRequest sn_request;
00094 static nKrawall::nPasswordAnswer sn_answer;
00095 static nKrawall::nSalt sn_salt;
00096 static int s_inUse = false;
00097
00098
00099 static void FinishHandlePasswordRequest()
00100 {
00101 nKrawall::nScrambledPassword egg;
00102
00103
00104 if (S_UserPasswordCallback)
00105 (*S_UserPasswordCallback)( sn_request, sn_answer );
00106
00107
00108 sn_GetAdr( 0, sn_answer.serverAddress );
00109 sn_request.ScrambleSalt( sn_salt, sn_answer.serverAddress );
00110
00111
00112 sn_request.ScrambleWithSalt( nKrawall::nScrambleInfo(sn_answer.username), sn_answer.scrambled, sn_salt, egg);
00113
00114
00115 sn_answer.scrambled.Clear();
00116
00117
00118 nMessage *ret = tNEW(nMessage)(nPasswordAnswer);
00119 nKrawall::WriteScrambledPassword(egg, *ret);
00120 *ret << sn_answer.username;
00121 *ret << sn_answer.aborted;
00122 *ret << sn_answer.automatic;
00123 *ret << sn_answer.serverAddress;
00124 ret->Send(0);
00125
00126 s_inUse = false;
00127 }
00128
00129
00130 void nAuthentication::HandlePasswordRequest(nMessage& m)
00131 {
00132 if (m.SenderID() > 0 || sn_GetNetState() != nCLIENT)
00133 Cheater(m.SenderID());
00134
00135 sn_answer = nKrawall::nPasswordAnswer();
00136 sn_request = nKrawall::nPasswordRequest();
00137
00138
00139 if ( s_inUse )
00140 return;
00141 s_inUse = true;
00142
00143
00144 ReadSalt(m, sn_salt);
00145
00146
00147 m.ReadRaw(sn_answer.username);
00148 sn_answer.username.NetFilter();
00149
00150 m >> sn_request.message;
00151 if (!m.End())
00152 {
00153 m >> sn_request.failureOnLastTry;
00154 }
00155 else
00156 {
00157 sn_request.failureOnLastTry = true;
00158 }
00159 if (!m.End())
00160 {
00161
00162 m >> sn_request.method;
00163 m.ReadRaw(sn_request.prefix);
00164 m.ReadRaw(sn_request.suffix);
00165 sn_request.prefix.NetFilter();
00166 sn_request.suffix.NetFilter();
00167 }
00168 else
00169 {
00170
00171 sn_request.method = "bmd5";
00172 sn_request.prefix = "";
00173 sn_request.suffix = "";
00174 }
00175
00176
00177
00178
00179 st_ToDo(&FinishHandlePasswordRequest);
00180 }
00181
00182 #ifdef KRAWALL_SERVER
00183
00184 static int sn_UserID( nNetObject * o )
00185 {
00186 if ( !o )
00187 {
00188 return -1;
00189 }
00190 return o->Owner();
00191 }
00192
00193 class nLoginProcess;
00194
00196 class nLoginPersistence:
00197 public nMachineDecorator
00198 {
00199 friend class nLoginProcess;
00200
00201 nLoginPersistence( int userID )
00202 : nMachineDecorator( nMachine::GetMachine( userID ) ),
00203 userAuthFailedLastTime( false )
00204 {
00205 }
00206
00207 static nLoginPersistence & Find( int userID )
00208 {
00209 nMachine & machine = nMachine::GetMachine( userID );
00210 nLoginPersistence * ret = machine.GetDecorator< nLoginPersistence >();
00211 if ( !ret )
00212 {
00213 ret = new nLoginPersistence( userID );
00214 }
00215
00216 return *ret;
00217 }
00218
00219 virtual void OnDestroy()
00220 {
00221 delete this;
00222 }
00223
00224 bool userAuthFailedLastTime;
00225 };
00226
00228 template< class T > class nMemberFunctionRunnerTemplate
00229 #ifdef HAVE_LIBZTHREAD
00230 : public ZThread::Runnable
00231 #endif
00232 {
00233 public:
00234 nMemberFunctionRunnerTemplate( T & object, void (T::*function)() )
00235 : object_( &object ), function_( function )
00236 {
00237 }
00238
00239
00240 void run()
00241 {
00242 (object_->*function_)();
00243 }
00244
00246 static void ScheduleBreak( T & object, void (T::*function)() )
00247 {
00248 pendingForBreak_.push_back( nMemberFunctionRunnerTemplate( object, function ) );
00249 }
00250
00252 static void ScheduleBackground( T & object, void (T::*function)() )
00253 {
00254 #ifdef HAVE_LIBZTHREAD
00255
00256 static nExecutor executor;
00257 if ( !tRecorder::IsRunning() )
00258 {
00259 executor.execute( ZThread::Task( new nMemberFunctionRunnerTemplate( object, function ) ) );
00260 }
00261 else
00262 {
00263
00264 ScheduleBreak( object, function );
00265
00266 }
00267 #else
00268
00269 ScheduleBreak( object, function );
00270 #endif
00271 }
00272
00274 static void ScheduleForeground( T & object, void (T::*function)() )
00275 {
00276 #ifdef HAVE_LIBZTHREAD
00277 Pending().add( nMemberFunctionRunnerTemplate( object, function ) );
00278 st_ToDo( FinishAll );
00279 #else
00280
00281 (object.*function)();
00282 #endif
00283
00284 }
00285
00286
00287 static void OnBreak()
00288 {
00289
00290 while( pendingForBreak_.size() > 0 )
00291 {
00292 nMemberFunctionRunnerTemplate & next = pendingForBreak_.front();
00293 next.run();
00294 pendingForBreak_.pop_front();
00295 }
00296 }
00297 private:
00299 tJUST_CONTROLLED_PTR< T > object_;
00300
00302 void (T::*function_)();
00303
00304
00305 static std::deque< nMemberFunctionRunnerTemplate > pendingForBreak_;
00306
00307 #ifdef HAVE_LIBZTHREAD
00308
00309 static ZThread::LockedQueue< nMemberFunctionRunnerTemplate, ZThread::FastMutex > & Pending()
00310 {
00311 static ZThread::LockedQueue< nMemberFunctionRunnerTemplate, ZThread::FastMutex > pending;
00312 return pending;
00313 }
00314
00315
00316 static void FinishAll()
00317 {
00318
00319 while( Pending().size() > 0 )
00320 {
00321 nMemberFunctionRunnerTemplate next = Pending().next();
00322 next.run();
00323 }
00324 }
00325 #endif
00326 };
00327
00328 template< class T >
00329 std::deque< nMemberFunctionRunnerTemplate<T> >
00330 nMemberFunctionRunnerTemplate<T>::pendingForBreak_;
00331
00332
00333 class nMemberFunctionRunner
00334 {
00335 public:
00336 enum ScheduleType
00337 {
00338 Break,
00339 Foreground,
00340 Background
00341 };
00342
00343 template< class T > static void ScheduleBreak( T & object, void (T::*function)() )
00344 {
00345 nMemberFunctionRunnerTemplate<T>::ScheduleBreak( object, function );
00346 }
00347
00348 template< class T > static void ScheduleBackground( T & object, void (T::*function)() )
00349 {
00350 nMemberFunctionRunnerTemplate<T>::ScheduleBackground( object, function );
00351 }
00352
00353 template< class T > static void ScheduleForeground( T & object, void (T::*function)() )
00354 {
00355 nMemberFunctionRunnerTemplate<T>::ScheduleForeground( object, function );
00356 }
00357
00358 template< class T > static void ScheduleMayBlock( T & object, void (T::*function)(), bool block )
00359 {
00360 if ( block )
00361 {
00362 #ifdef HAVE_LIBZTHREAD
00363 ScheduleBackground( object, function );
00364 #else
00365 ScheduleBreak( object, function );
00366 #endif
00367 }
00368 else
00369 {
00370 ScheduleForeground( object, function );
00371 }
00372 }
00373 };
00374
00375
00377 class nLoginProcess:
00378 public nMachineDecorator,
00379 public nKrawall::nCheckResult,
00380 public nKrawall::nPasswordCheckData,
00381 public tReferencable< nLoginProcess, nMutex >
00382 {
00383
00384 typedef tJUST_CONTROLLED_PTR< nLoginProcess > SelfPointer;
00385 public:
00386 nLoginProcess( int userID )
00387 : nMachineDecorator( nMachine::GetMachine( userID ) )
00388 {
00389
00390 selfReference_ = this;
00391
00392
00393 bool delays = false;
00394 #ifdef HAVE_LIBZTHREAD
00395 delays = tRecorder::IsRunning();
00396 #endif
00397 if ( delays )
00398 {
00399 sn_ConsoleOut( tOutput( "$login_message_delayed" ), userID );
00400 }
00401 }
00402
00403 ~nLoginProcess()
00404 {
00405 }
00406
00407 static nLoginProcess * Find( int userID )
00408 {
00409 nMachine & machine = nMachine::GetMachine( userID );
00410 return machine.GetDecorator< nLoginProcess >();
00411 }
00412
00413
00414 void Init( tString const & authority, tString const & username, nNetObject & user, tString const & message )
00415 {
00416 this->user = &user;
00417 this->username = username;
00418 this->message = message;
00419 this->authority = authority;
00420
00421 clientSupportedMethods = sn_Connections[user.Owner()].supportedAuthenticationMethods_;
00422
00423 nMemberFunctionRunner::ScheduleMayBlock( *this, &nLoginProcess::FetchInfoFromAuthority, authority != "" );
00424 }
00425
00426
00427
00428 void FetchInfoFromAuthority();
00429
00430
00431 bool ReportAuthorityError( tOutput const & error )
00432 {
00433
00434 this->success = false;
00435 this->error = error;
00436
00437 Abort();
00438
00439 return false;
00440 }
00441
00442
00443
00444
00445 void QueryFromClient();
00446
00447
00448 void ProcessClientAnswer( nMessage & answer );
00449
00450
00451 bool CheckServerAddress( nMessage & m );
00452
00453
00454
00455 void Authorize();
00456
00457
00458
00459 void Finish();
00460
00461
00462 void Abort();
00463 private:
00464
00465
00466
00467 bool FetchInfoFromAuthorityRemote();
00468
00469
00470 bool FetchInfoFromAuthorityLocal();
00471
00472 tString message;
00473
00474
00475 tString clientSupportedMethods;
00476
00477
00478
00479
00480 virtual void OnDestroy()
00481 {
00482 SelfPointer keepAlive( this );
00483 selfReference_ = 0;
00484 }
00485
00487 SelfPointer selfReference_;
00488 };
00489
00490
00491
00492
00493
00494 void nLoginProcess::FetchInfoFromAuthority()
00495 {
00496
00497 method.method = "bmd5";
00498 method.prefix = "";
00499 method.suffix = "";
00500
00501 bool ret;
00502 if ( !tRecorder::IsPlayingBack() )
00503 {
00504 if ( authority.Len() <= 1 )
00505 {
00506
00507 ret = FetchInfoFromAuthorityLocal();
00508 }
00509 else
00510 {
00511
00512 ret = FetchInfoFromAuthorityRemote();
00513 }
00514 }
00515
00516
00517 static char const * section = "AUTH_INFO";
00518 tRecorder::Playback( section, ret );
00519 tRecorder::Playback( section, method.method );
00520 tRecorder::Playback( section, method.prefix );
00521 tRecorder::Playback( section, method.suffix );
00522 tRecorder::Playback( section, authority );
00523 tRecorder::Playback( section, error );
00524 tRecorder::Record( section, ret );
00525 tRecorder::Record( section, method.method );
00526 tRecorder::Record( section, method.prefix );
00527 tRecorder::Record( section, method.suffix );
00528 tRecorder::Record( section, authority );
00529 tRecorder::Record( section, error );
00530
00531 if ( !ret )
00532 {
00533 if ( tRecorder::IsPlayingBack() )
00534 {
00535 Abort();
00536 }
00537
00538 return;
00539 }
00540
00541
00542 nMemberFunctionRunner::ScheduleForeground( *this, &nLoginProcess::QueryFromClient );
00543 }
00544
00545 static bool sn_supportRemoteLogins = false;
00546 static tSettingItem< bool > sn_supportRemoteLoginsConf( "GLOBAL_ID", sn_supportRemoteLogins );
00547
00548
00549 static bool sn_IsLegalSpecialChar( char c )
00550 {
00551 switch (c)
00552 {
00553 case '-':
00554 case '+':
00555 case '=':
00556 case '_':
00557 return true;
00558 default:
00559 return false;
00560 }
00561 }
00562
00563
00564 bool nLoginProcess::FetchInfoFromAuthorityRemote()
00565 {
00566 if ( !sn_supportRemoteLogins )
00567 {
00568 return ReportAuthorityError( tOutput("$login_error_noremote") );
00569 }
00570
00571 {
00572
00573 #ifdef DEBUG
00574 if ( tIsInList( sn_AuthorityNoCheck, authority ) )
00575 {
00576 fullAuthority = authority;
00577 }
00578 else
00579 #endif
00580 {
00581 std::istringstream in( static_cast< const char * >( authority ) );
00582 std::ostringstream outShort;
00583 std::ostringstream outFull;
00584 int c = in.get();
00585
00586
00587 bool shortcut = true;
00588
00589
00590 bool rawIP = true;
00591
00592
00593 bool inHostName = true;
00594 bool inPort = false;
00595 bool slash = false;
00596 int port = 0;
00597
00598 while( !in.eof() )
00599 {
00600 if ( inHostName )
00601 {
00602
00603 if ( c == '.' )
00604 {
00605 shortcut = false;
00606 }
00607 else if ( isalnum(c) )
00608 {
00609 c = tolower(c);
00610 if ( !isdigit( c ) )
00611 {
00612 rawIP = false;
00613 }
00614 }
00615 else if ( c == ':' )
00616 {
00617 inPort = true;
00618 inHostName = false;
00619 }
00620 else if ( c == '/' )
00621 {
00622 shortcut = false;
00623 slash = true;
00624 inHostName = false;
00625 }
00626 else if ( !sn_IsLegalSpecialChar(c) )
00627 {
00628 return ReportAuthorityError( tOutput( "$login_error_invalidurl_illegal_hostname", authority ) );
00629 }
00630 }
00631 else if ( inPort )
00632 {
00633 if ( c == '/' )
00634 {
00635 shortcut = false;
00636 inPort = false;
00637 slash = true;
00638 }
00639 else if ( !isdigit( c ) )
00640 {
00641 return ReportAuthorityError( tOutput( "$login_error_invalidurl_illegal_port", authority ) );
00642 }
00643 else
00644 {
00645 port *= 10;
00646 port += c - '0';
00647 }
00648 }
00649 else
00650 {
00651 if ( c == '/' )
00652 {
00653 if ( slash )
00654 {
00655 return ReportAuthorityError( tOutput( "$login_error_invalidurl_slash", authority ) );
00656 }
00657
00658 slash = true;
00659 }
00660 else
00661 {
00662 if (!isalnum(c) && c != '.' && c != '~' && !sn_IsLegalSpecialChar(c) )
00663 {
00664 return ReportAuthorityError( tOutput( "$login_error_invalidurl_illegal_path", authority ) );
00665 }
00666
00667 slash = false;
00668 }
00669 }
00670
00671
00672 outShort.put(tolower(c));
00673
00674 outFull.put(c);
00675
00676 c = in.get();
00677 }
00678 if ( slash )
00679 {
00680 return ReportAuthorityError( tOutput( "$login_error_invalidurl_slash", authority ) );
00681 }
00682 if ( port == 80 )
00683 {
00684 return ReportAuthorityError( tOutput( "$login_error_invalidurl_defaultport", authority ) );
00685 }
00686
00687 if ( rawIP )
00688 {
00689 return ReportAuthorityError( tOutput( "$login_error_invalidurl_rawip", authority ) );
00690 }
00691
00692 authority = outShort.str().c_str();
00693 fullAuthority = outFull.str().c_str();
00694
00695 static const char * def = ".authentication.armagetronad.net";
00696
00697
00698 if ( authority.Len() > 1 && shortcut )
00699 {
00700 fullAuthority += def;
00701 }
00702
00703
00704 if ( !shortcut && authority.Reverse().StartsWith( tString( def ).Reverse() ) )
00705 {
00706
00707 authority = authority.SubStr( 0, authority.Len() - strlen( def ) - 1 );
00708 shortcut = true;
00709 }
00710 }
00711
00712
00713 if ( tIsInList( sn_AuthorityBlacklist, authority ) )
00714 {
00715 return ReportAuthorityError( tOutput( "$login_error_blacklist", authority ) );
00716 }
00717
00718 if ( sn_AuthorityWhitelist != "" && !tIsInList( sn_AuthorityWhitelist, authority ) )
00719 {
00720 return ReportAuthorityError( tOutput( "$login_error_whitelist", authority ) );
00721 }
00722
00723
00724 std::stringstream answer;
00725 int rc = nKrawall::FetchURL( fullAuthority, "?query=methods", answer );
00726
00727 if ( rc == -1 )
00728 {
00729 return ReportAuthorityError( tOutput( "$login_error_invalidurl_notfound", authority ) );
00730 }
00731
00732 tString id;
00733 answer >> id;
00734 tToLower(id);
00735
00736 tString methods;
00737 std::ws(answer);
00738 methods.ReadLine( answer );
00739 tToLower(methods);
00740
00741 if ( rc != 200 || id != "methods" )
00742 {
00743 return ReportAuthorityError( tOutput( "$login_error_nomethodlist", authority, rc, id + " " + methods ) );
00744 }
00745
00746
00747 method.method = nKrawall::nMethod::BestMethod(
00748 methods,
00749 clientSupportedMethods
00750 );
00751
00752
00753 if ( method.method.Len() <= 1 )
00754 {
00755 return ReportAuthorityError(
00756 tOutput( "$login_error_nomethod",
00757 clientSupportedMethods,
00758 nKrawall::nMethod::SupportedMethods(),
00759 methods )
00760 );
00761 }
00762 }
00763
00764
00765 {
00766 std::ostringstream query;
00767 query << "?query=params";
00768 query << "&method=" << nKrawall::EncodeString( method.method );
00769 std::ostringstream data;
00770 int rc = nKrawall::FetchURL( fullAuthority, query.str().c_str(), data );
00771
00772 if ( rc != 200 )
00773 {
00774 if ( rc == -1 )
00775 {
00776 return ReportAuthorityError( tOutput( "$login_error_invalidurl_notfound", authority ) );
00777 }
00778
00779 return ReportAuthorityError( tOutput( "$login_error_nomethodproperties", authority, rc, data.str().c_str() ) );
00780 }
00781
00782
00783 std::istringstream read( data.str() );
00784 method = nKrawall::nMethod( static_cast< char const * >( method.method ), read );
00785 }
00786
00787 return true;
00788 }
00789
00790
00791 bool nLoginProcess::FetchInfoFromAuthorityLocal()
00792 {
00793
00794 if ( !nKrawall::nMethod::BestLocalMethod(
00795 clientSupportedMethods,
00796 method
00797 )
00798 )
00799 {
00800 return ReportAuthorityError(
00801 tOutput( "$login_error_nomethod",
00802 clientSupportedMethods,
00803 nKrawall::nMethod::SupportedMethods(),
00804 nKrawall::nMethod::SupportedMethods() )
00805 );
00806 }
00807
00808 return true;
00809 }
00810
00811
00812
00813
00814 void nLoginProcess::QueryFromClient()
00815 {
00816
00817
00818 int userID = sn_UserID( user );
00819 if ( userID <= 0 )
00820 return;
00821
00822
00823 nKrawall::RandomSalt(salt);
00824
00825
00826 nMessage *m = tNEW(nMessage)(::nPasswordRequest);
00827 nKrawall::WriteSalt(salt, *m);
00828 *m << username;
00829 *m << static_cast<tString>(message);
00830 *m << nLoginPersistence::Find( userID ).userAuthFailedLastTime;
00831
00832
00833 *m << method.method;
00834 *m << method.prefix;
00835 *m << method.suffix;
00836
00837 m->Send(userID);
00838
00839
00840 con << tOutput( "$login_message_responded", userID, username, method.method, message );
00841 }
00842
00843
00844 void nLoginProcess::ProcessClientAnswer( nMessage & m )
00845 {
00846 success = false;
00847
00848
00849 nKrawall::ReadScrambledPassword(m, hash);
00850
00851 m.ReadRaw(username);
00852 username.NetFilter();
00853
00854 aborted = false;
00855 automatic = false;
00856 if ( !m.End() )
00857 {
00858 m >> aborted;
00859 }
00860 if ( !m.End() )
00861 {
00862 m >> automatic;
00863 }
00864 if (!m.End())
00865 {
00866
00867 m >> serverAddress;
00868
00869
00870 if ( !CheckServerAddress( m ) )
00871 {
00872
00873 return;
00874 }
00875 }
00876 else
00877 {
00878 serverAddress = sn_GetMyAddress();
00879
00880 if ( method.method != "bmd5" )
00881 {
00882 con << "WARNING, client did not send the server address. Password checks may fail.\n";
00883 }
00884 }
00885
00886
00887 nMemberFunctionRunner::ScheduleMayBlock( *this, &nLoginProcess::Authorize, authority != "" );
00888 }
00889
00890 static bool sn_trustLAN = false;
00891 static tSettingItem< bool > sn_TrustLANConf( "TRUST_LAN", sn_trustLAN );
00892
00893
00894 bool nLoginProcess::CheckServerAddress( nMessage & m )
00895 {
00896
00897 nSocket const * socket = sn_Connections[m.SenderID()].socket;
00898 if ( socket )
00899 {
00900 tString compareAddress = socket->GetAddress().ToString();
00901 if ( !compareAddress.StartsWith("*") && compareAddress == serverAddress )
00902 {
00903
00904 return true;
00905 }
00906 }
00907
00908
00909 if ( sn_trustLAN )
00910 {
00911 tString peerAddress;
00912 sn_GetAdr( m.SenderID(), peerAddress );
00913 if ( sn_IsLANAddress( peerAddress ) && sn_IsLANAddress( serverAddress ) )
00914 {
00915 return true;
00916 }
00917 }
00918
00919 else if ( sn_GetMyAddress() == serverAddress )
00920 {
00921
00922 return true;
00923 }
00924
00925 tString hisServerAddress = serverAddress;
00926 serverAddress = sn_GetMyAddress();
00927
00928
00929 if ( sn_GetMyAddress().StartsWith("*") )
00930 {
00931
00932 return ReportAuthorityError( tOutput("$login_error_pharm", hisServerAddress, sn_GetMyAddress() ) );
00933 }
00934
00935
00936 return ReportAuthorityError( tOutput("$login_error_pharm", hisServerAddress, sn_GetMyAddress() ) );
00937 }
00938
00939
00940
00941 void nLoginProcess::Authorize()
00942 {
00943 if ( aborted )
00944 {
00945 success = false;
00946
00947 error = tOutput("$login_error_aborted");
00948 }
00949 else
00950 {
00951 if ( !tRecorder::IsPlayingBack() )
00952 {
00953 nKrawall::CheckScrambledPassword( *this, *this );
00954 }
00955
00956
00957
00958
00959
00960 static char const * section = "AUTH_RESULT";
00961 tRecorder::Playback( section, username );
00962 tRecorder::Playback( section, success );
00963 tRecorder::Playback( section, authority );
00964 tRecorder::Playback( section, error );
00965 tRecorder::Record( section, username );
00966 tRecorder::Record( section, success );
00967 tRecorder::Record( section, authority );
00968 tRecorder::Record( section, error );
00969 }
00970
00971 Abort();
00972 }
00973
00974
00975 void nLoginProcess::Abort()
00976 {
00977 nMemberFunctionRunner::ScheduleForeground( *this, &nLoginProcess::Finish );
00978 }
00979
00980
00981
00982 void nLoginProcess::Finish()
00983 {
00984
00985 int userID = sn_UserID( user );
00986 if ( userID <= 0 )
00987 return;
00988
00989
00990 nCurrentSenderID currentSender( userID );
00991
00992
00993 nLoginPersistence::Find( userID ).userAuthFailedLastTime = !success;
00994
00995
00996 Remove();
00997
00998 if (S_LoginResultCallback)
00999 (*S_LoginResultCallback)( *this );
01000
01001
01002 Destroy();
01003 }
01004
01005 static void sn_Reset(){
01006 int userID = nCallbackLoginLogout::User();
01007
01008
01009 nLoginProcess * process = nLoginProcess::Find( userID );
01010 if ( process )
01011 {
01012 process->Remove();
01013 process->Destroy();
01014 }
01015 }
01016
01017 static nCallbackLoginLogout reset(&sn_Reset);
01018
01019 #endif // KRAWALL_SERVER
01020
01021 void nAuthentication::HandlePasswordAnswer(nMessage& m)
01022 {
01023 #ifdef KRAWALL_SERVER
01024
01025 nLoginProcess * process = nLoginProcess::Find( m.SenderID() );
01026
01027
01028 if ( process )
01029 {
01030 process->ProcessClientAnswer( m );
01031 }
01032 #endif
01033 }
01034
01035
01036 bool nAuthentication::RequestLogin(const tString & authority, const tString& username, nNetObject & user, const tOutput& message )
01037 {
01038 #ifdef KRAWALL_SERVER
01039 int userID = user.Owner();
01040 if ( userID <= 0 )
01041 {
01042 return false;
01043 }
01044
01045 con << tOutput( "$login_message_requested", userID, username, authority );
01046
01047
01048 if ( nLoginProcess::Find( userID ) )
01049 {
01050 return false;
01051 }
01052
01053
01054 (new nLoginProcess( userID ))->Init( authority, username, user, tString(message) );
01055 #endif
01056
01057 return true;
01058 }
01059
01061 void nAuthentication::OnBreak()
01062 {
01063 #ifdef KRAWALL_SERVER
01064 nMemberFunctionRunnerTemplate< nLoginProcess >::OnBreak();
01065 #endif
01066 st_DoToDo();
01067 }
01068