Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
NetAuth.cpp
Go to the documentation of this file.
1 /* Project Starshatter 4.5
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: Stars.exe
6  FILE: NetAuth.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  This class represents a user connecting to the multiplayer lobby
13 */
14 
15 
16 #include "MemDebug.h"
17 #include "NetAuth.h"
18 #include "NetLobby.h"
19 #include "NetUser.h"
20 #include "ModConfig.h"
21 #include "ModInfo.h"
22 #include "Random.h"
23 #include "sha1.h"
24 
25 static int auth_level = NetAuth::NET_AUTH_MINIMAL;
26 
27 // +-------------------------------------------------------------------+
28 
29 int
31 {
32  return auth_level;
33 }
34 
35 
36 void
38 {
39  if (n >= NET_AUTH_MINIMAL && n <= NET_AUTH_SECURE)
40  auth_level = n;
41 }
42 
43 // +-------------------------------------------------------------------+
44 
45 Text
47 {
48  Text request;
49 
50  if (u) {
51  u->SetAuthLevel(auth_level);
52 
53  if (auth_level == NET_AUTH_MINIMAL) {
55  u->SetSalt("Very Low Sodium");
56  }
57 
58  else if (auth_level == NET_AUTH_STANDARD) {
60  u->SetSalt("Very Low Sodium");
61 
62  request = "level 1";
63  }
64 
65  else {
66  char salt[33];
67 
68  for (int i = 0; i < 32; i++)
69  salt[i] = (char) ('0' + (int) Random(0, 9.4));
70 
71  salt[32] = 0;
72  u->SetSalt(salt);
74 
75  request = "level 2 salt ";
76  request += salt;
77  }
78  }
79 
80  return request;
81 }
82 
83 // +-------------------------------------------------------------------+
84 
85 static Text Digest(const char* salt, const char* file)
86 {
87  int length = 0;
88  int offset = 0;
89  char block[4096];
90  char digest[64];
91 
92  ZeroMemory(digest, sizeof(digest));
93 
94  if (file) {
95  FILE* f;
96  fopen_s(&f, file, "rb");
97 
98  if (f) {
99  SHA1 sha1;
100 
101  if (salt) {
102  sha1.Input(salt, strlen(salt));
103  }
104 
105  fseek(f, 0, SEEK_END);
106  length = ftell(f);
107  fseek(f, 0, SEEK_SET);
108 
109  while (offset < length) {
110  int n = fread(block, sizeof(char), 4096, f);
111  sha1.Input(block, n);
112  offset += n;
113  }
114 
115  fclose(f);
116 
117  unsigned result[5];
118  if (sha1.Result(result)) {
119  sprintf_s(digest, "SHA1_%08X_%08X_%08X_%08X_%08X",
120  result[0], result[1], result[2], result[3], result[4]);
121  }
122  }
123  }
124 
125  return digest;
126 }
127 
128 // +-------------------------------------------------------------------+
129 
130 Text
131 NetAuth::CreateAuthResponse(int level, const char* salt)
132 {
133  Text response;
134  ModConfig* config = ModConfig::GetInstance();
135 
136  if (level == NET_AUTH_SECURE) {
137 
138 #ifdef STARSHATTER_DEMO_RELEASE
139 
140  response += "exe ";
141  response += Digest(salt, "StarDemo.exe"); // XXX should look up name of this exe
142  response += " ";
143 
144 #else
145 
146  response += "exe ";
147  response += Digest(salt, "stars.exe"); // XXX should look up name of this exe
148  response += " ";
149 
150 #endif
151 
152  response += "dat ";
153  response += Digest(salt, "shatter.dat");
154  response += " ";
155 
156  response += "etc ";
157  response += Digest(salt, "start.dat");
158  response += " ";
159  }
160 
161  if (level >= NET_AUTH_STANDARD) {
162  List<ModInfo>& mods = config->GetModInfoList();
163  ListIter<ModInfo> mod_iter = mods;
164 
165  char buffer[32];
166  sprintf_s(buffer, "num %d ", mods.size());
167  response += buffer;
168 
169  while (++mod_iter) {
170  ModInfo* info = mod_iter.value();
171 
172  response += "mod \"";
173  response += info->Name();
174  response += "\" ver \"";
175  response += info->Version();
176  response += "\" ";
177 
178  if (level == NET_AUTH_SECURE) {
179  response += "sha ";
180  response += Digest(salt, info->Filename());
181  response += " ";
182  }
183  }
184  }
185 
186  return response;
187 }
188 
189 // +-------------------------------------------------------------------+
190 
191 bool
193 {
194  bool authentic = false;
195 
196  if (auth_level == NET_AUTH_MINIMAL) { // (this case should not occur)
197  if (u) {
198  u->SetAuthLevel(auth_level);
200  }
201 
202  authentic = (u != 0);
203  }
204 
205  else if (u) {
206  Text expected_response = CreateAuthResponse(auth_level, u->Salt());
207  if (expected_response == response)
208  authentic = true;
209 
210  u->SetAuthState(authentic ? NET_AUTH_OK : NET_AUTH_FAILED);
211  }
212 
213  return authentic;
214 }
215 
216 // +-------------------------------------------------------------------+
217