* Added password change support (references #95)
* Fixed 64bit support * Repaired line endings * Bumped protocol version
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user