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  response += "exe ";
138  response += Digest(salt, "stars.exe"); // XXX should look up name of this exe
139  response += " ";
140 
141  response += "dat ";
142  response += Digest(salt, "shatter.dat");
143  response += " ";
144 
145  response += "etc ";
146  response += Digest(salt, "start.dat");
147  response += " ";
148  }
149 
150  if (level >= NET_AUTH_STANDARD) {
151  List<ModInfo>& mods = config->GetModInfoList();
152  ListIter<ModInfo> mod_iter = mods;
153 
154  char buffer[32];
155  sprintf_s(buffer, "num %d ", mods.size());
156  response += buffer;
157 
158  while (++mod_iter) {
159  ModInfo* info = mod_iter.value();
160 
161  response += "mod \"";
162  response += info->Name();
163  response += "\" ver \"";
164  response += info->Version();
165  response += "\" ";
166 
167  if (level == NET_AUTH_SECURE) {
168  response += "sha ";
169  response += Digest(salt, info->Filename());
170  response += " ";
171  }
172  }
173  }
174 
175  return response;
176 }
177 
178 // +-------------------------------------------------------------------+
179 
180 bool
182 {
183  bool authentic = false;
184 
185  if (auth_level == NET_AUTH_MINIMAL) { // (this case should not occur)
186  if (u) {
187  u->SetAuthLevel(auth_level);
189  }
190 
191  authentic = (u != 0);
192  }
193 
194  else if (u) {
195  Text expected_response = CreateAuthResponse(auth_level, u->Salt());
196  if (expected_response == response)
197  authentic = true;
198 
199  u->SetAuthState(authentic ? NET_AUTH_OK : NET_AUTH_FAILED);
200  }
201 
202  return authentic;
203 }
204 
205 // +-------------------------------------------------------------------+
206