Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2013-01

Controlling access to a method

7 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mark Morgan Lloyd

Given a fragment of code like this:

type
   TDbConfigFrame = class(TFrame)
..
   public
     { public declarations }
     property DbInit: TDbConfigInit write fdbInit;
   end;

is there any way of enforcing a rule that DbInit can only be written by (for example) a descendant of TForm or TNotebook? Or only being writable by e.g. the OnCreate() method of certain designated form instances?

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Hans-Peter Diettrich
to Mark Morgan Lloyd
Show quoted text 9 lines
Given a fragment of code like this: type TDbConfigFrame = class(TFrame) .. public { public declarations } property DbInit: TDbConfigInit write fdbInit; end;

A write-only property can be implemented by a (setter) procedure, to which you add whatever arguments may be useful (e.g. Sender).

is there any way of enforcing a rule that DbInit can only be written by (for example) a descendant of TForm or TNotebook? Or only being writable by e.g. the OnCreate() method of certain designated form instances?

You can check Sender against the owner of the frame, if that helps.

DoDi

Reply by email

Mark Morgan Lloyd
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 12 lines
Mark Morgan Lloyd schrieb: > Given a fragment of code like this: > > type > TDbConfigFrame = class(TFrame) > .. > public > { public declarations } > property DbInit: TDbConfigInit write fdbInit; > end; A write-only property can be implemented by a (setter) procedure,

Yes, I was assuming that.

to which you add whatever arguments may be useful (e.g. Sender).

OK, but in that case I presume that you can no longer go via the object's property (reserved word).

Also in that case I presume that some unauthorised caller could spoof an explicit sender parameter.

Is there a reliable way to walk the stack and get a list of senders? I presume at the very least that LineInfo would be needed for this, and that the executable would have to be unstripped.

Show quoted text 6 lines
> is there any way of enforcing a rule that DbInit can only be written > by (for example) a descendant of TForm or TNotebook? Or only being > writable by e.g. the OnCreate() method of certain designated form > instances? You can check Sender against the owner of the frame, if that helps.

Yes, that I like. However I think the problem is still getting the sender in such a way that it can't be spoofed.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Mattias Gaertner
to Mark Morgan Lloyd: Given a fragment of code like this: type TDbConfigFrame = class(TFrame) .. public {…
Show quoted text 13 lines
Given a fragment of code like this: type TDbConfigFrame = class(TFrame) .. public { public declarations } property DbInit: TDbConfigInit write fdbInit; end; is there any way of enforcing a rule that DbInit can only be written by (for example) a descendant of TForm or TNotebook? Or only being writable by e.g. the OnCreate() method of certain designated form instances?

Why not add a method

procedure TDbConfigFrame.SetDBInit(Setter: TComponent;
  NewInit: TDbConfigInit);
begin
  if not ((Setter is TForm) or (Setter is TNoteBook)) then
    raise Exception.Create('not allowed');
  fdbinit:=NewInit;
end;

Mattias

Reply by email

Hans-Peter Diettrich
to Mark Morgan Lloyd: Yes, I was assuming that. OK, but in that case I presume that you can no longer go via the
Show quoted text 20 lines
Hans-Peter Diettrich wrote: > Mark Morgan Lloyd schrieb: >> Given a fragment of code like this: >> >> type >> TDbConfigFrame = class(TFrame) >> .. >> public >> { public declarations } >> property DbInit: TDbConfigInit write fdbInit; >> end; > > A write-only property can be implemented by a (setter) procedure, Yes, I was assuming that. > to which you add whatever arguments may be useful (e.g. Sender). OK, but in that case I presume that you can no longer go via the object's property (reserved word).

Why do you need both?

Also in that case I presume that some unauthorised caller could spoof an explicit sender parameter.

What degree of security do you expect?

Would it be sufficient to initialize the field in the constructor? Then you could add an constructor that takes the value, and make the field inaccessible to other code (private).

Show quoted text 13 lines
Is there a reliable way to walk the stack and get a list of senders? I presume at the very least that LineInfo would be needed for this, and that the executable would have to be unstripped. >> is there any way of enforcing a rule that DbInit can only be written >> by (for example) a descendant of TForm or TNotebook? Or only being >> writable by e.g. the OnCreate() method of certain designated form >> instances? > > You can check Sender against the owner of the frame, if that helps. Yes, that I like. However I think the problem is still getting the sender in such a way that it can't be spoofed.

He who can read your source code also can modify it, to get rid of all your protection attempts.

DoDi

Reply by email

Mark Morgan Lloyd
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 23 lines
Mark Morgan Lloyd schrieb: > Hans-Peter Diettrich wrote: >> Mark Morgan Lloyd schrieb: >>> Given a fragment of code like this: >>> >>> type >>> TDbConfigFrame = class(TFrame) >>> .. >>> public >>> { public declarations } >>> property DbInit: TDbConfigInit write fdbInit; >>> end; >> >> A write-only property can be implemented by a (setter) procedure, > > Yes, I was assuming that. > >> to which you add whatever arguments may be useful (e.g. Sender). > > OK, but in that case I presume that you can no longer go via the > object's property (reserved word). Why do you need both?

You don't, I was assuming that being unobtrusive was an advantage,

Show quoted text 8 lines
> Also in that case I presume that some unauthorised caller could spoof > an explicit sender parameter. What degree of security do you expect? Would it be sufficient to initialize the field in the constructor? Then you could add an constructor that takes the value, and make the field inaccessible to other code (private).

..

He who can read your source code also can modify it, to get rid of all your protection attempts.

I'd settle for protecting my code from its original author :-)

You are of course entirely right: from the POV of protecting against silly mistykes it's entirely adequate to have a validation parameter, even if it's not used for anything else. I was originally thinking about it from the POV of bare-metal protected-mode code, where you could explicitly bind a procedure to ring 2 thus protecting it from ring 3 access.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Hans-Peter Diettrich
to Mark Morgan Lloyd
You are of course entirely right: from the POV of protecting against silly mistykes it's entirely adequate to have a validation parameter, even if it's not used for anything else.

If only one initialization is sufficient, the property setter can reject any further changes, after the value has been set to something other than "uninitialized". I use such protection frequently, for properties which cannot be changed after initialization of an object.

I was originally thinking about it from the POV of bare-metal protected-mode code, where you could explicitly bind a procedure to ring 2 thus protecting it from ring 3 access.

This only defers the authorization problem, to controlling ring transitions. You can introduce a global "RingLevel" variable, checkable in every protected procedure. Then everything depends on controlling the write access (for rights elevation) to that variable. IMO this doesn't help much, since when a subroutine is allowed to increase the ringlevel for one purpose, it will be allowed subsequently to call *all* other protected subroutines as well.

Another idea: every creator of an object can keep the object private, so that nobody else can access it. This is impossible for an TFrame, which is listed in the public Controls[] and Components[] lists. In this case another "lock" object can be used, known only to the creator and the protected object/procedure, as a spoofing protection.

Or you use "private" or "implementation" clause visibility. Then only code inside that unit can access such a variable or field.

DoDi

Reply by email