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