mainform.pas
来自「著名的SecureBlackBox控件完整源码」· PAS 代码 · 共 900 行 · 第 1/2 页
PAS
900 行
ClientsSharedResource.WaitToWrite;
try
Client := TSimpleClient.Create;
{ Assign its default values }
Client.DNS := AContext.Connection.Socket.Binding.PeerIP;
Client.Name := AContext.Connection.Socket.Binding.PeerIP;
Client.Context := AContext;
{ SSH ClientServer IOhandler initialization }
Client.SSHCSIOHandler :=
TElIdSSHClientServerIOHandler(AContext.Connection.IOHandler);
Client.SSHCSIOHandler.OnOpenChannel := Client.HandleOpenConnection;
Client.SSHCSIOHandler.OnAuthAttempt := Client.HandleAuthAttempt;
Client.SSHCSIOHandler.OnAuthPassword := Client.HandleAuthPassword;
Client.SSHCSIOHandler.OnError := Client.HandleError;
Client.SSHDataConnection := nil;
{ Assign it to the thread so we can identify it later }
AContext.Data := Client;
{ Add it to the clients list }
Clients.Add(Client);
{ updating clients list }
UpdateClientList;
finally
ClientsSharedResource.Done;
end;
end;
end;
procedure TfrmMain.tcpServerDisconnect(AContext: TIdContext);
var
Client : TSimpleClient;
begin
ClientsSharedResource.WaitToWrite;
try
{ Retrieve Client Record from Data pointer }
Client := Pointer(AContext.Data);
if Assigned(Client) then
begin
{ Remove Client from the Clients list }
Clients.Delete(Clients.IndexOf(Client));
UpdateClientList;
{ Broadcast leaving message }
SendText(nil, '** ' + Client.Name + ' disconnected.');
SendText(nil, ClientList);
{ Free the Client object }
Client.Free;
AContext.Data := nil;
end;
finally
ClientsSharedResource.Done;
end;
end;
procedure TfrmMain.tcpServerExecute(AContext: TIdContext);
var
Client : TSimpleClient;
Com, Msg : String;
begin
{ Get the clients package info }
Client := Pointer(AContext.Data);
if not Assigned(Client.SSHCSIOHandler) then
begin
AContext.Connection.Disconnect;
Exit;
end;
Client.SSHCSIOHandler.DataAvailable;
if (Client.SSHCSIOHandler.Active) and Assigned(Client.SSHDataConnection) then
begin
{ Get the text sent from the client }
Msg := RecvText(Client);
{ If name is set, then send the message }
if Length(Msg) = 0 then
begin
Sleep(100);
Exit;
end;
if Msg[1] <> '@' then
begin
SendText(nil, Client.Name + '>' + Msg);
end
else
begin
{ System command }
Com := UpperCase(Trim(Copy(Msg, 2, Pos(':', Msg) -2)));
Msg := Trim(Copy(Msg, Pos(':', Msg) +1, Length(Msg)));
if Com = 'CLIENTS' then
begin
SendText(Client, ClientList);
AddToLog('** Clientlist request from ' + Client.Name);
end
else if Com = 'MSG' then
begin
SendText(nil, Client.Name + '>' + Msg);
end;
end;
end;
end;
procedure TfrmMain.DisconnectClient(Client: TSimpleClient; const Reason: string);
begin
if Assigned(Client.SSHDataConnection) and
(Client.SSHDataConnection.Connected) then
begin
try
SendText(Client, edSysopName.Text + '>' + Reason);
except
end;
end;
if Assigned(Client.SSHCSIOHandler) then
try
Client.SSHCSIOHandler.Close;
except
end;
end;
procedure TfrmMain.btnLoadKeyClick(Sender: TObject);
var
Res : integer;
Key : TElSSHKey;
begin
if dlgLoadKey.Execute then
begin
Key := TElSSHKey.Create;
try
Res := Key.LoadPrivateKey(dlgLoadKey.FileName, '');
if Res = 0 then
SetServerKey(Key)
else
if Res = SB_ERROR_SSH_KEYS_INVALID_PASSPHRASE then
begin
Res := frmPassword.ShowModal;
if Res = mrOk then
begin
Res := Key.LoadPrivateKey(dlgLoadKey.FileName, frmPassword.edPassword.Text);
if Res = 0 then
SetServerKey(Key)
else
Application.MessageBox('Incorrect passphrase!','Error', MB_OK);
end;
end
else
Application.MessageBox('Cannot load server key!','Error', MB_OK);
finally
Key.Free;
end;
end;
end;
procedure TfrmMain.SendText(Client : TSimpleClient; const Msg: string);
var
I : integer;
begin
if Client = nil then
begin
{ broadcasting message to all connected users }
for I := 0 to Clients.Count - 1 do
SendText(Clients[I], Msg);
if (Length(Msg) > 0) and (Msg[1] <> '@') then
AddToLog(Msg);
end
else
begin
if Assigned(Client.SSHDataConnection)
then
try
Client.SSHDataConnection.IOHandler.WriteLn(Msg);
except
on E : Exception do
begin
AddToLog('** Client ' + Client.Name + ' error : ' + E.Message);
DisconnectClient(Client, '');
end;
end;
end;
end;
procedure TfrmMain.AddToLog(const Str: string);
begin
memLog.Lines.Add(Str);
end;
function TfrmMain.ClientList: string;
begin
Result := '@CLIENTS:' + lbClients.Items.CommaText;
end;
function TfrmMain.RecvText(Client: TSimpleClient): string;
begin
if Assigned(Client) and Assigned(Client.SSHDataConnection)
and (Client.SSHDataConnection.Connected) then
begin
try
Result := Client.SSHDataConnection.IOHandler.ReadLn('', 5);
except
on E : Exception do
begin
Result := '';
AddToLog('** Client ' + Client.Name + ' error : ' + E.Message);
DisconnectClient(Client, '');
end;
end;
end;
end;
{ TSimpleClient }
constructor TSimpleClient.Create;
begin
inherited;
Name := '';
Context := nil;
SSHCSIOHandler := nil;
SSHDataConnection := nil;
end;
destructor TSimpleClient.Destroy;
begin
if Assigned(SSHCSIOHandler) then
FreeAndNil(SSHCSIOHandler);
if Assigned(SSHDataConnection) then
FreeAndNil(SSHDataConnection);
inherited;
end;
procedure TSimpleClient.HandleAuthPassword(Sender: TObject; const Username,
Password: string; var Accept, ForceChangePassword: boolean);
var
Index : integer;
Digest : TMessageDigest160;
begin
Accept := false;
for Index := 0 to frmMain.AllowedClients.Count - 1 do
if LowerCase(Trim(Username)) =
LowerCase(Trim(TAllowedClientInfo(frmMain.AllowedClients[Index]).Login)) then
begin
if TAllowedClientInfo(frmMain.AllowedClients[Index]).HasPassword then
begin
Digest := HashSHA1(Password);
if CompareMD160(Digest, TAllowedClientInfo(frmMain.AllowedClients[Index]).Digest) then
begin
Accept := true;
Name := Username;
Exit;
end;
end
else
begin
Accept := true;
Name := Username;
Exit;
end;
end;
frmMain.AddToLog('** Authentication failed for user ' + Username);
end;
procedure TSimpleClient.HandleAuthAttempt(Sender: TObject;
const Username: string; AuthType: integer; var Accept: boolean);
begin
if not (AuthType = SSH_AUTH_TYPE_PASSWORD) then
Accept := false
else
Accept := true;
end;
procedure TSimpleClient.HandleOpenConnection(Sender: TObject;
Connection: TElIdSSHConnection);
begin
{ checking connection type }
if (Connection.TunnelType = ttSubsystem) and (Connection.Subsystem = 'chat') then
begin
frmMain.AddToLog(Format('** Opened channel to client %s', [Self.Name]));
SSHDataConnection := Connection;
frmMain.SendText(Self, frmMain.memEntry.Text);
frmMain.UpdateClientList;
frmMain.SendText(nil, frmMain.ClientList);
end;
end;
procedure TSimpleClient.HandleError(Sender: TObject; ErrorCode: integer);
begin
frmMain.AddToLog(Format('** Client %s SSH error %d, disconnecting.', [Name, ErrorCode]));
end;
procedure TfrmMain.btnRefreshClick(Sender: TObject);
begin
LoadAllowedClientsList;
end;
procedure TfrmMain.UpdateAllowedClientsList;
var
Index : integer;
Str : string;
begin
lbAllowedUsers.Clear;
for Index := 0 to AllowedClients.Count - 1 do
begin
Str := TAllowedClientInfo(AllowedClients[Index]).Login;
if TAllowedClientInfo(AllowedClients[Index]).HasPassword then
Str := Str + '(*)';
lbAllowedUsers.Items.AddObject(Str, AllowedClients[Index]);
end;
end;
procedure TfrmMain.LoadAllowedClientsList;
var
FUsers : TextFile;
UStr, Hash, Login : string;
I : integer;
Digest : TMessageDigest160;
UInfo : TAllowedClientInfo;
begin
AllowedClients.Clear;
if FileExists('.chat_users') then
try
System.Assign(FUsers, '.chat_users');
ReSet(FUsers);
while not EOF(FUsers) do
begin
ReadLn(FUsers, UStr);
I := Pos(':', UStr);
if I > 0 then
begin
Login := Copy(UStr, 1, I - 1);
Hash := Trim(Copy(Ustr, I + 1, Length(UStr) - I));
UInfo := TAllowedClientInfo.Create;
UInfo.Login := Login;
if (Length(Hash) = 40) and (SBUtils.StrToDigest(Hash, Digest)) then
begin
UInfo.Digest := Digest;
UInfo.HasPassword := true;
end
else
UInfo.HasPassword := false;
AllowedClients.Add(UInfo);
end;
end;
System.Close(FUsers);
finally
end;
UpdateAllowedClientsList;
end;
procedure TfrmMain.btnAddUserClick(Sender: TObject);
var
UserInfo : TAllowedClientInfo;
Login : string;
begin
Login := InputBox('Adding user..', 'Enter login : ', '');
if Login <> '' then
begin
UserInfo := TAllowedClientInfo.Create;
UserInfo.Login := Login;
UserInfo.HasPassword := false;
AllowedClients.Add(UserInfo);
UpdateAllowedClientsList;
end;
end;
procedure TfrmMain.btnSetPasswordClick(Sender: TObject);
var
UInfo : TAllowedClientInfo;
Index : integer;
Password : string;
begin
Index := lbAllowedUsers.ItemIndex;
if Index < 0 then Exit;
UInfo := TAllowedClientInfo(lbAllowedUsers.Items.Objects[Index]);
if Assigned(UInfo) then
begin
Password := InputBox('New password', 'Password (empty to remove):', '');
if Password = '' then
begin
FillChar(UInfo.Digest, SizeOf(UInfo.Digest), 0);
UInfo.HasPassword := false;
end
else
begin
UInfo.Digest := HashSHA1(Password);
UInfo.HasPassword := true;
end;
end;
UpdateAllowedClientsList;
end;
procedure TfrmMain.btnSaveClick(Sender: TObject);
var
FUsers : TextFile;
Index : integer;
begin
try
System.Assign(FUsers, '.chat_users');
ReWrite(FUsers);
for Index := 0 to AllowedClients.Count - 1 do
begin
Write(FUsers, TAllowedClientInfo(AllowedClients[Index]).Login, ':');
if TAllowedClientInfo(AllowedClients[Index]).HasPassword then
begin
WriteLn(FUsers, DigestToStr(TAllowedClientInfo(AllowedClients[Index]).Digest));
end
else
WriteLn(FUsers);
end;
System.Close(FUsers);
finally
end;
UpdateAllowedClientsList;
end;
procedure TfrmMain.btnDelUserClick(Sender: TObject);
var
UInfo : TAllowedClientInfo;
Index : integer;
begin
Index := lbAllowedUsers.ItemIndex;
if Index < 0 then Exit;
UInfo := TAllowedClientInfo(lbAllowedUsers.Items.Objects[Index]);
AllowedClients.Remove(UInfo);
UpdateAllowedClientsList;
end;
end.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?