3
votes

In Delphi XE2 / Indy 10, I've been doing some work on a few Web Broker projects which include a web module capturing particular http requests, and if there's no particular matching request, it searches for a file from within a root directory. Now what I'm trying to do is implement security around certain files and file extensions, just like in a typical web server such as IIS.

Is there something in Indy or at least in Delphi XE2 which can manage this security? Or is it something I will have to encapsulate myself? Because I have a different method in each of my projects, and I'd rather there be a standard way to do it in all of them than to re-invent the wheel.

3
as Darian answered, you're on your own, however, you have the flexibility of doing "does it match X? give Y, otherwise disconnect client" and on top of that, your code is not public, an attacker would be blind.user497849
@ComputerSaysNo, in HTTP you not supposed to "disconnect client".OnTheFly
@user539484 well, I do, if they do something wrong in a sensitive area, they get disconnected faster than a blink of an eye.user497849
@ComputerSaysNo, you are doing it wrong, then.OnTheFly
@ComputerSaysNo, I got your idea from the first comment and it is very bad idea. In the fact forcible tearing off "bad" connections violates HTTP specs and opens an another attack vector.OnTheFly

3 Answers

5
votes

You are on your own for security implementation. HTTP Server gives you events to respond to and you'll need to consider access within those events.

5
votes

Indy HTTP Server (TIdHTTPServer) supports HTTP Basic Authentication with the properties AuthExists, AuthUser and AuthPass of the Request object and the Response.AuthRealm property. (I have not checked if NTLM or Digest auth are supported also).

By setting the AuthRealm property in the Response, the client will be notified that a Basic Authentification is required. If the client sends the username and password in the request, the server can check it in the command handler.

So actually Indy provides built-in support for securing resources - this works both with a normal browser and with a REST client, both will only be able to access server resources if the request includes the auth header.

I have implemented it also in my Indy based (commercial) web framework. The example code secures all content on the server and has a hard coded user name / password combination.

procedure TBasicAuthHandlerWrapper.Handle(Target: string; Context:
  TdjServerContext;
  Request: TIdHTTPRequestInfo; Response: TIdHTTPResponseInfo);
const
  AUTH_USER = 'sherlock';
  AUTH_PASS = 'holmes';
begin
  if Request.AuthExists and ((Request.AuthUsername = AUTH_USER) and
    (Request.AuthPassword = AUTH_PASS)) then
  begin
    // pass
    inherited;
  end
  else
  begin
    // show login dialog
    Response.AuthRealm := 'Welcome to Web Components Server!';
  end;
end;

Note: this example protects all resources independent of extension and path. But this is easy to add in the method body, by checking conditions of the path which is available in Request.Document.

0
votes

I work correctly with all browsers I've tried inserting the basic authentication check directly in the "get" method of TIdHttpServer as an example :

procedure TForm2.IdHTTPServer1CommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
  tmpVal: string;
  ts: TStringList;
  rs: TResourceStream;
  FilePath: string;
  ReturnMainPage: Boolean;
begin
 if (edUser.Text <> '') or (edPassword.Text <> '') then
  Begin
   if (ARequestInfo.AuthPassword.ToLower <>edUser.Text.ToLower) and (ARequestInfo.AuthUsername <>edPassword.Text) then
    begin
    AResponseInfo.ResponseNo := 401;
    AResponseInfo.ResponseText := 'Authorization required';
    AResponseInfo.ContentType := 'text/html';
    AResponseInfo.ContentText := '<html>Authorization required</html>';
    AResponseInfo.CustomHeaders.Values['WWW-Authenticate'] := 'Basic ...your values here ...';
    AResponseInfo.AuthRealm := 'Welcome to Synaptica OnAirController';
    Exit;
    end;
  End;

I realized this as inserting a component TIdHttpServer on a form where I have two Tedit I use to enter username and password . Obviously this little thing is not correct for a production system but it is an example.