1 /* 2 3 ************************************************************************* 4 5 ArmageTron -- Just another Tron Lightcycle Game in 3D. 6 Copyright (C) 2000 Manuel Moos (manuel@moosnet.de) 7 8 ************************************************************************** 9 10 This program is free software; you can redistribute it and/or 11 modify it under the terms of the GNU General Public License 12 as published by the Free Software Foundation; either version 2 13 of the License, or (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 23 24 *************************************************************************** 25 26 Although it is already included in the GPL, let me clarify: 27 anybody, especially the Krawall Gaming network, is allowed 28 to run a server/master server build from modified versions of 29 this file WHITHOUT releasing the source to the public (provided 30 the executable is not distributed). 31 32 */ 33 34 #ifndef ArmageTron_NKRAWALL_H 35 #define ArmageTron_NKRAWALL_H 36 37 //#include <iosfwd> 38 //#include <iostream> 39 40 #include "defs.h" 41 #include "config.h" 42 #include "md5.h" 43 #include "tSafePTR.h" 44 #include "tString.h" 45 // #include "nNetObject.h" 46 #include "tConfiguration.h" 47 48 #include <deque> 49 50 class nNetObject; 51 52 #ifndef _IOSFWD_ 53 #endif 54 55 //#error x 56 57 class tString; 58 class nMessage; 59 60 //! base class for authentication, unaware of armagetron network messages 61 class nKrawall 62 { 63 public: 64 // the scrambled password data types 65 class nScrambledPassword 66 { 67 friend class nKrawall; 68 69 md5_byte_t content[16]; 70 public: 71 md5_byte_t operator[]( int i ) const 72 { 73 tASSERT( i >= 0 && i < 16 ); 74 return content[i]; 75 } 76 77 md5_byte_t & operator[]( int i ) 78 { 79 tASSERT( i >= 0 && i < 16 ); 80 return content[i]; 81 } 82 Clear()83 void Clear() 84 { 85 memset( &content, 0, sizeof(content)); 86 } 87 }; 88 89 typedef nScrambledPassword nSalt; // (freely changable) 90 91 //! extra information for password scrambling 92 struct nScrambleInfo 93 { 94 tString username; //!< the username 95 nScrambleInfonScrambleInfo96 nScrambleInfo( tString const & username_ ) 97 : username( username_) 98 { 99 } 100 }; 101 102 //! authentication method information 103 struct nMethod 104 { 105 tString method; //!< scrambling method; "bmd5" for old school 106 tString prefix; //!< thing to prepend the password before hashing it 107 tString suffix; //!< thing to append to the password before hashing it 108 109 // returns a comma separated list of supported methods 110 static tString SupportedMethods(); 111 112 // from two strings of supported-method-lists, select the best one 113 static tString BestMethod( tString const & a, tString const & b ); 114 115 // scramble a password using this 116 void ScramblePassword( nScrambleInfo const & info, tString const & password, nScrambledPassword & scrambled ) const; 117 118 //! extra salt scrambling step, done on client and server, not on authentication server 119 void ScrambleSalt( nSalt & salt, tString const & serverIP ) const; 120 121 //! scramble a password hash with a salt 122 void ScrambleWithSalt( nScrambleInfo const & info, nScrambledPassword const & scrambled, nSalt const & salt, nScrambledPassword & result ) const; 123 124 //! fetch NULL-terminated list of locally supported methods 125 static nMethod const * const * LocalMethods(); 126 127 //! fetch best local method supported by the client 128 static bool BestLocalMethod( tString const & supportedOnClient, nMethod & result ); 129 130 //! compare two methods 131 static bool Equal( nMethod const & a, nMethod const & b ); 132 nMethodnMethod133 nMethod(){} 134 135 // construct a method from the type and a stream with properties 136 // the stream is supposed to consist of lines of the "property_name property_value" form. 137 nMethod( char const * method_, std::istream & properties ); 138 139 nMethod( char const * method_, char const * prefix_ = "", char const * suffix_ = ""); 140 }; 141 142 // structure for a password request to the user 143 struct nPasswordRequest: public nMethod 144 { 145 tString message; // message to show to the user 146 bool failureOnLastTry; // did the last attempt fail? 147 nPasswordRequestnPasswordRequest148 nPasswordRequest() 149 : failureOnLastTry ( false ){} 150 }; 151 152 // structure for read-write data for password requests 153 struct nPasswordAnswer 154 { 155 tString serverAddress; // the address of the server 156 tString username; // username, read-write property 157 nScrambledPassword scrambled; // the scrambled password 158 bool aborted; // did the user abort the operation? 159 bool automatic; // was the answer provided automatically without user interaction? 160 nPasswordAnswernPasswordAnswer161 nPasswordAnswer() 162 : aborted( false ), automatic( false ){} 163 }; 164 165 struct nPasswordCheckData 166 { 167 tString fullAuthority; // authority (no shorthand version); authenticated name is username@authority 168 nMethod method; //!< method of authentication 169 nSalt salt; //!< the salt used in the authentication process 170 nScrambledPassword hash; //!< hash as sent from client 171 tString serverAddress; //!< server address used for MITM protection 172 }; 173 174 // return structure for an authentication request 175 struct nCheckResultBase 176 { 177 tString username; // username as sent from client 178 tString authority; // authority (shorthand version allowed); authenticated name is username@authority 179 bool success; // was the operation successful? 180 tString error; // potential error message 181 std::deque< tString > blurb; // additional blurb data the authority may give on successful login 182 183 tAccessLevel accessLevel;// access level of user 184 nCheckResultBasenCheckResultBase185 nCheckResultBase() 186 : success( false ), accessLevel( tAccessLevel_Authenticated ){} 187 }; 188 189 struct nCheckResult: public nCheckResultBase 190 { 191 tJUST_CONTROLLED_PTR< nNetObject > user; // net object identifying the user (will be ePlayerNetID, but we don't know about that here) 192 bool aborted; // did the user abort the operation? 193 bool automatic; // was the answer provided automatically without user interaction? 194 195 nCheckResult(); 196 ~nCheckResult(); 197 nCheckResult( nCheckResult const & other ); 198 }; 199 200 // encode scrambled passwords and salts as hexcode strings 201 static tString EncodeScrambledPassword( nScrambledPassword const & scrambled ); 202 203 // encode a string for safe inclusion into an URL 204 static tString EncodeString( tString const & original ); 205 206 // network read/write operations of these data types 207 static void WriteScrambledPassword(const nScrambledPassword& scrambled, 208 nMessage &m); 209 210 static void ReadScrambledPassword( nMessage &m, 211 nScrambledPassword& scrambled); 212 213 // file read/write operations of these data types 214 static void WriteScrambledPassword(const nScrambledPassword& scrambled, 215 std::ostream &s); 216 217 static void ReadScrambledPassword( std::istream &s, 218 nScrambledPassword& scrambled); 219 220 WriteSalt(const nSalt & salt,nMessage & m)221 static void WriteSalt(const nSalt& salt, 222 nMessage &m) 223 { 224 WriteScrambledPassword(salt, m); 225 } 226 ReadSalt(nMessage & m,nSalt & salt)227 static void ReadSalt( nMessage &m, 228 nSalt& salt) 229 { 230 ReadScrambledPassword(m, salt); 231 } 232 233 // compare two passwords 234 static bool ArePasswordsEqual(const nScrambledPassword& a, 235 const nScrambledPassword& b); 236 237 238 // scramble a password locally (so it does not have to be stored on disk) 239 static void ScramblePassword(const tString& password, 240 nScrambledPassword &scrambled); 241 242 // scramble a password locally (so it does not have to be stored on disk), old broken method that includes the trailing \0. 243 static void BrokenScramblePassword(const tString& password, 244 nScrambledPassword &scrambled); 245 246 // scramble it again before transfering it over the network 247 static void ScrambleWithSalt2(const nScrambledPassword& source, 248 const nSalt& salt, 249 nScrambledPassword& dest); 250 251 252 // get a random salt value 253 static void RandomSalt(nSalt& salt); 254 #ifdef KRAWALL_SERVER 255 //! split a fully qualified user name in authority and username part 256 static void SplitUserName( tString const & original, tString & username, tString & authority ); 257 static void SplitBaseAuthorityName( tString const & authority, tString & base ); 258 static bool CanClaim( tString contacted, tString claimed ); 259 260 // check whether username's password, when run through ScrambleWithSalt( ScramblePassword(password), salt ), equals scrambledRemote. result.userName and result.authority need to be set by the caller, success and error are filled by this function, and authority may be modified. 261 static void CheckScrambledPassword( nCheckResultBase & result, 262 nPasswordCheckData const & data ); 263 264 // fetches an URL content, return http return code (-1 if total failure), fill result stream. 265 static int FetchURL( tString const & authority, char const * query, std::ostream & target, int maxlen = 10000 ); 266 267 #ifdef KRAWALL_SERVER_LEAGUE 268 // secret key to encrypt server->master server league transfer 269 static const nScrambledPassword& SecretLeagueKey(); 270 271 // called on the servers to create a league message 272 static void SendLeagueMessage(const tString& message = *reinterpret_cast<tString *>(0)); 273 274 // called on the master server when the league message is received 275 static void ReceiveLeagueMessage(const tString& message); 276 277 // league message generation functions: fill message with the message to be 278 // sent 279 280 // called when victim drives against killer's wall 281 static void Frag(const tString &killer, const tString& victim, tString& message); 282 283 // called at the end of a round; the last survivor is stored in 284 // players[numPlayers-1], the first death in players[0] 285 static void RoundEnd(const tString* players, int numPlayers, tString& message); 286 287 // called ON THE SERVER when victim drives against killer's wall 288 static void ServerFrag(const tString &killer, const tString& victim); 289 290 // called ON THE SERVER at the end of a round; the last survivor is stored in 291 // players[numPlayers-1], the first death in players[0] 292 static void ServerRoundEnd(const tString* players, int numPlayers); 293 294 295 // called ON THE MASTER when victim drives against killer's wall 296 static void MasterFrag(const tString &killer, const tString& victim); 297 298 // called ON THE MASTER at the end of a round; the last survivor is stored in 299 // players[numPlayers-1], the first death in players[0] 300 static void MasterRoundEnd(const tString* players, int numPlayers); 301 302 // Adress checking functions 303 304 // first validity check for the league messages 305 static bool IsFromKrawall(tString& adress, unsigned int port); 306 307 // check if a user is from germany (so the master server will require 308 // a password check) 309 static bool RequireMasterLogin(tString& adress, unsigned int port); 310 311 // only servers acknowledged by this funktion are from Krawall and 312 // are allowed to request logins 313 static bool MayRequirePassword(tString& adress, unsigned int port); 314 #endif 315 #endif 316 }; 317 318 #endif 319