* Added password change support (references #95)

* Fixed 64bit support
* Repaired line endings
* Bumped protocol version
This commit is contained in:
2013-11-20 18:12:52 +01:00
parent 9676549ac3
commit 829a604c30
35 changed files with 21115 additions and 20710 deletions

View File

@@ -21,7 +21,7 @@
* CDDL HEADER END
*
*
* Portions Copyright 2008 Andreas Schneider
* Portions Copyright 2013 Andreas Schneider
*)
unit UAccount;
@@ -37,7 +37,7 @@ type
{ TAccount }
TAccount = class(TObject, ISerializable, IInvalidate)
constructor Create(AOwner: IInvalidate; AName, APasswordHash: string;
constructor Create(AOwner: IInvalidate; AName, APassword: string;
AAccessLevel: TAccessLevel; ARegions: TStringList);
constructor Deserialize(AOwner: IInvalidate; AElement: TDOMElement);
destructor Destroy; override;
@@ -58,7 +58,9 @@ type
property PasswordHash: string read FPasswordHash write SetPasswordHash;
property LastPos: TPoint read FLastPos write SetLastPos;
property Regions: TStringList read FRegions;
function CheckPassword(APassword: String): Boolean;
procedure Invalidate;
procedure UpdatePassword(APassword: String);
end;
{ TAccountList }
@@ -79,17 +81,17 @@ type
implementation
uses
UCEDServer, UConfig;
UCEDServer, UConfig, md5;
{ TAccount }
constructor TAccount.Create(AOwner: IInvalidate; AName, APasswordHash: string;
constructor TAccount.Create(AOwner: IInvalidate; AName, APassword: string;
AAccessLevel: TAccessLevel; ARegions: TStringList);
begin
inherited Create;
FOwner := AOwner;
FName := AName;
FPasswordHash := APasswordHash;
FPasswordHash := MD5Print(MD5String(APassword));
FAccessLevel := AAccessLevel;
if ARegions <> nil then
FRegions := ARegions
@@ -154,11 +156,27 @@ begin
Invalidate;
end;
function TAccount.CheckPassword(APassword: String): Boolean;
var
testHash: String;
begin
//Since I want to change to PBKDF2 sometime, we compare strings instead
//of MD5Digest, so we can (later) check what type of hash the string has
//been created with.
testHash := MD5Print(MD5String(APassword));
Result := FPasswordHash = testHash;
end;
procedure TAccount.Invalidate;
begin
FOwner.Invalidate;
end;
procedure TAccount.UpdatePassword(APassword: String);
begin
PasswordHash := MD5Print(MD5String(APassword));
end;
procedure TAccount.Serialize(AElement: TDOMElement);
var
i: Integer;

View File

@@ -21,7 +21,7 @@
* CDDL HEADER END
*
*
* Portions Copyright 2008 Andreas Schneider
* Portions Copyright 2013 Andreas Schneider
*)
unit UAdminHandling;
@@ -88,7 +88,7 @@ var
implementation
uses
md5, UCEDServer, UPackets, UClientHandling;
UCEDServer, UPackets, UClientHandling;
procedure AdminBroadcast(AAccessLevel: TAccessLevel; APacket: TPacket);
var
@@ -146,7 +146,7 @@ begin
if account <> nil then
begin
if password <> '' then
account.PasswordHash := MD5Print(MD5String(password));
account.UpdatePassword(password);
account.AccessLevel := accessLevel;
@@ -181,8 +181,8 @@ begin
for i := 0 to regionCount - 1 do
regions.Add(ABuffer.ReadStringNull);
account := TAccount.Create(Config.Accounts, username,
MD5Print(MD5String(password)), accessLevel, regions);
account := TAccount.Create(Config.Accounts, username, password,
accessLevel, regions);
Config.Accounts.Add(account);
Config.Accounts.Invalidate;

View File

@@ -217,7 +217,7 @@ begin
try
buffer := ANetState.ReceiveQueue;
buffer.Position := 0;
while (buffer.Size >= 1) and ANetState.Socket.Connected do
while (buffer.Size >= 1) and (ANetState.Socket.ConnectionStatus = scConnected) do
begin
packetID := buffer.ReadByte;
packetHandler := PacketHandlers[packetID];
@@ -268,7 +268,7 @@ begin
netState := TNetState(FTCPServer.Iterator.UserData);
if netState <> nil then
begin
if FTCPServer.Iterator.Connected then
if FTCPServer.Iterator.ConnectionStatus = scConnected then
begin
if (SecondsBetween(netState.LastAction, Now) > 120) then
begin
@@ -326,7 +326,7 @@ begin
while FTCPServer.IterNext do
begin
netState := TNetState(FTCPServer.Iterator.UserData);
if (netState <> nil) and (FTCPServer.Iterator.Connected) then
if (netState <> nil) and (FTCPServer.Iterator.ConnectionStatus = scConnected) then
begin
netState.SendQueue.Seek(0, soFromEnd);
netState.SendQueue.CopyFrom(APacket.Stream, 0);
@@ -340,7 +340,7 @@ end;
procedure TCEDServer.Disconnect(ASocket: TLSocket);
begin
if ASocket.Connected then
if ASocket.ConnectionStatus = scConnected then
begin
ASocket.Disconnect;
//OnDisconnect(ASocket);

View File

@@ -71,6 +71,12 @@ type
constructor Create(AAccount: TAccount);
end;
{ TPasswordChangeStatusPacket }
TPasswordChangeStatusPacket = class(TPacket)
constructor Create(AResult: TPasswordChangeStatus);
end;
procedure OnClientHandlerPacket(ABuffer: TEnhancedMemoryStream;
ANetState: TNetState);
procedure OnUpdateClientPosPacket(ABuffer: TEnhancedMemoryStream;
@@ -79,6 +85,8 @@ procedure OnChatMessagePacket(ABuffer: TEnhancedMemoryStream;
ANetState: TNetState);
procedure OnGotoClientPosPacket(ABuffer: TEnhancedMemoryStream;
ANetState: TNetState);
procedure OnChangePasswordPacket(ABuffer: TEnhancedMemoryStream;
ANetState: TNetState);
procedure WriteAccountRestrictions(AStream: TEnhancedMemoryStream;
AAccount: TAccount);
@@ -130,6 +138,44 @@ begin
TSetClientPosPacket.Create(account.LastPos));
end;
procedure OnChangePasswordPacket(ABuffer: TEnhancedMemoryStream;
ANetState: TNetState);
var
oldPwd, newPwd: String;
begin
oldPwd := ABuffer.ReadStringNull;
newPwd := ABuffer.ReadStringNull;
if ANetState.Account.CheckPassword(oldPwd) then
begin
//Check if the passwords actually differ. Changing them isn't allowed
//otherwise. Might be open for configuration, though.
if oldPwd <> newPwd then
begin
//Just a simple restriction to disallow too easy passwords.
//TODO: Configurable restrictions
if Length(newPwd) >= 4 then
begin
//Everything fine, update the password and report success.
ANetState.Account.UpdatePassword(newPwd);
CEDServerInstance.SendPacket(ANetState,
TPasswordChangeStatusPacket.Create(pcSuccess));
end else
begin
CEDServerInstance.SendPacket(ANetState,
TPasswordChangeStatusPacket.Create(pcNewPwInvalid));
end;
end else
begin
CEDServerInstance.SendPacket(ANetState,
TPasswordChangeStatusPacket.Create(pcIdentical));
end;
end else
begin
CEDServerInstance.SendPacket(ANetState,
TPasswordChangeStatusPacket.Create(pcOldPwInvalid));
end;
end;
procedure WriteAccountRestrictions(AStream: TEnhancedMemoryStream;
AAccount: TAccount);
var
@@ -236,6 +282,15 @@ begin
WriteAccountRestrictions(FStream, AAccount);
end;
{ TPasswordChangeStatusPacket }
constructor TPasswordChangeStatusPacket.Create(AResult: TPasswordChangeStatus);
begin
inherited Create($0C, 0);
FStream.WriteByte($08);
FStream.WriteByte(Byte(AResult));
end;
{$WARNINGS OFF}
var
i: Integer;
@@ -246,6 +301,7 @@ initialization
ClientPacketHandlers[$04] := TPacketHandler.Create(0, @OnUpdateClientPosPacket);
ClientPacketHandlers[$05] := TPacketHandler.Create(0, @OnChatMessagePacket);
ClientPacketHandlers[$06] := TPacketHandler.Create(0, @OnGotoClientPosPacket);
ClientPacketHandlers[$08] := TPacketHandler.Create(0, @OnChangePasswordPacket);
finalization
for i := 0 to $FF do
if ClientPacketHandlers[i] <> nil then

View File

@@ -21,7 +21,7 @@
* CDDL HEADER END
*
*
* Portions Copyright 2008 Andreas Schneider
* Portions Copyright 2013 Andreas Schneider
*)
unit UConfig;
@@ -30,8 +30,8 @@ unit UConfig;
interface
uses
Classes, SysUtils, DOM, XMLRead, XMLWrite, md5, Keyboard, UAccount,
UXmlHelper, UInterfaces, UEnums, URegions;
Classes, SysUtils, DOM, XMLRead, XMLWrite, Keyboard, UAccount, UXmlHelper,
UInterfaces, UEnums, URegions;
type
@@ -292,8 +292,8 @@ begin
until stringValue <> '';
Write ('Password [hidden]: ');
password := QueryPassword;
FAccounts.Add(TAccount.Create(FAccounts, stringValue,
MD5Print(MD5String(password)), alAdministrator, nil));
FAccounts.Add(TAccount.Create(FAccounts, stringValue, password,
alAdministrator, nil));
FChanged := True;
end;

View File

@@ -21,7 +21,7 @@
* CDDL HEADER END
*
*
* Portions Copyright 2008 Andreas Schneider
* Portions Copyright 2013 Andreas Schneider
*)
unit UConnectionHandling;
@@ -63,7 +63,7 @@ var
implementation
uses
md5, UCEDServer, UClientHandling, UPackets;
UCEDServer, UClientHandling, UPackets;
procedure OnConnectionHandlerPacket(ABuffer: TEnhancedMemoryStream; ANetState: TNetState);
var
@@ -77,19 +77,19 @@ end;
procedure OnLoginRequestPacket(ABuffer: TEnhancedMemoryStream;
ANetState: TNetState);
var
username, passwordHash: string;
username, password: string;
account: TAccount;
netState: TNetState;
invalid: Boolean;
begin
username := ABuffer.ReadStringNull;
passwordHash := MD5Print(MD5String(ABuffer.ReadStringNull));
password := ABuffer.ReadStringNull;
account := Config.Accounts.Find(username);
if account <> nil then
begin
if account.AccessLevel > alNone then
begin
if account.PasswordHash = passwordHash then
if account.CheckPassword(password) then
begin
invalid := False;
CEDServerInstance.TCPServer.IterReset;

View File

@@ -139,7 +139,7 @@ begin
begin
subscriptions := CEDServerInstance.Landscape.BlockSubscriptions[ACoords[i].X, ACoords[i].Y];
subscriptions.Delete(ANetState);
subscriptions.Add(Integer(ANetState), ANetState);
subscriptions.Add(PtrInt(ANetState), ANetState);
if ANetState.Subscriptions.IndexOf(subscriptions) = -1 then
ANetState.Subscriptions.Add(subscriptions);
end;

View File

@@ -1,4 +1,4 @@
<?xml version="1.0"?>
<?xml version="1.0" encoding="UTF-8"?>
<CONFIG>
<ProjectOptions>
<Version Value="9"/>
@@ -13,9 +13,9 @@
<VersionInfo>
<UseVersionInfo Value="True"/>
<MinorVersionNr Value="6"/>
<RevisionNr Value="3"/>
<RevisionNr Value="4"/>
<BuildNr Value="240"/>
<StringTable CompanyName="AKS DataBasis" ProductName="CentrED" InternalName="CentrED Server" LegalCopyright="(c) 2012 Andreas Schneider" ProductVersion="0.6.3" FileDescription="CentrED Server" OriginalFilename="cedserver.exe"/>
<StringTable CompanyName="AKS DataBasis" FileDescription="CentrED Server" InternalName="CentrED Server" LegalCopyright="(c) 2013 Andreas Schneider" OriginalFilename="cedserver.exe" ProductName="CentrED" ProductVersion="0.6.4"/>
</VersionInfo>
<BuildModes Count="3">
<Item1 Name="default" Default="True"/>
@@ -69,7 +69,7 @@
</Item2>
<Item3 Name="Release Win32">
<MacroValues Count="1">
<Macro1 Name="LCLWidgetType" Value="win32"/>
<Macro2 Name="LCLWidgetType" Value="win32"/>
</MacroValues>
<CompilerOptions>
<Version Value="11"/>
@@ -115,6 +115,10 @@
</Other>
</CompilerOptions>
</Item3>
<SharedMatrixOptions Count="2">
<Item1 ID="285940101796" Modes="Release Linux i686" Type="IDEMacro" MacroName="LCLWidgetType" Value="gtk2"/>
<Item2 ID="285439860087" Modes="Release Win32" Type="IDEMacro" MacroName="LCLWidgetType" Value="win32"/>
</SharedMatrixOptions>
</BuildModes>
<PublishOptions>
<Version Value="2"/>
@@ -231,7 +235,6 @@
<Parsing>
<SyntaxOptions>
<CStyleOperator Value="False"/>
<UseAnsiStrings Value="False"/>
</SyntaxOptions>
</Parsing>
<Linking>