Phantasmal MUD Lib for DGD

Phantasmal Site > DGD > DGD LPC Reference > DGD Calling Conventions

DGD Function Calling Conventions

Date: Wed, 10 Jun 1998 17:29:34 +0200 (MET DST)
From: Frank Schmidt
Subject: [DGD] Re: Couple DGD questions


On Tue, 9 Jun 1998, E. Harte wrote:

> On Tue, 9 Jun 1998, Stephen Schmidt wrote:
> 
> [...questions about kfuns...]
> 
> Making a function static in the auto-object only has an effect on
> call_other() type of calls to such functions.  I.e: if "foobar" is a
> static function in your auto-object then "someobj"->foobar() will return
> 0, _unless_ "someobj" has defined its own foobar() function which isn't
> static.

No, as you describe it, that is the way it works for other objects BUT the
auto object, and an object may access its own static functions through
call_other, i.e: call_other(this_object(), "static_func") works.

In the auto object, a static function behaves like a kernel function
(kfun) _too_: It cannot be accessed by call_other(this_object(),
"kfun_func"), _and_ calls to it in the auto object are _not_ redirected
to any masked function in this_object(). This is true for ALL static
functionnames in the auto object, not just the default functions
specified by the driver you happen to override.


> 
> So, to consider your write_file() and valid_write() example, I'd either
> make the valid_write() nomask, or private to the auto-object, yes.
> Otherwise something like the following could disable your security:
> 
> <auto-object>
> static int
> valid_write(string filename)
> {
> }
> 
> static void
> write_file(string filename)
> {
> }
> </auto-object>
> 
> <other-object>
> static int
> valid_write(string filename)
> {
>     return 1; /* of course ;) */
> }
> </other-object>

No, sorry, but this will not disable his security IF the security call is
made in the auto object, but it will override the call made in an
inherited program. This is ambigous, and is of course not wanted. However,
I dislike overuse of nomask due to lack of knowledge about kfuns. In many
situations, nomask creates a false sense of secureness, overlooking the
more important holes.

I set a BIG questionmark (?) to this way to deal with security too.
Instead of having the valid_ functions in each and every object, make a
daemon which any object may call_other() and query about security issues
and similar. 

(An equivalent of MudOS Master object is nice, or you may split it up in
several daemons. The way I deal with it is a master.c object for
simple queries, and a global.c object for call_out(), heart_beat(), etc,
global issues. The main point is to globalise functions and datas in
sentral objects.)

> 
> 
> There is another situation where kfuns are showing how they're different:
> 
>   If you are using a certain kfun in the auto-object which you have -not-
>   redefined, for instance you're using this_object() or previous_object(),
>   then no matter how hard you try to redefine those in another object, the
>   code in the auto-object will continue to use the -kfun- and not the
>   redefined version.

This is true for redefines kfuns in the auto object too.

> 
> Sometimes I wish there was a way to make static functions in the auto-
> object behave the same way without having to nomask them. :-)

Nomasking a function makes it impossible to overload in an inheriting
program. However, that is not the same as static, private or kfun, since
you can still access a nomasked function!

And.. Your wishes have come true! It is possible to make the functions
behave like kfuns, just declare them static in the auto object. And it is
VERY convinient, flexible and elegant. :)

> 
> > Second, and unrelated; it is now the case that when an object is
> > compiled, create() is not called right away; it's called only
> > when the first function is called in the object. This caused me
> > a great deal of headache tonight when I couldn't figure out why
> > create() was not running, which was solved when I RTFM.  :)
> > Question is, why was this changed?

Arrgh. I didn't know this. Thanks for the information, it was new to me,
a simple test showed that it was correct. When a master program is
compiled (I really prefer calling them blueprint because of my Master
object..) the create function is not called before the first function is
called in the object, and for clones the create function is called right
away.

> 
> What makes you think this changed?  As far as I remember, the 'create'
> function (or whichever name you pick for this function) was for non-clones
> always called just before you tried to call any other function in the
> object for the first time.

Maybe, but I too missed that point. Any ref. to where in the docs this is
explained?

> 
> > It seems unintuitive for
> > master copies of objects not to invoke create(), I find myself
> > having to code around it (not hard to do) but in general I do
> > not see a way for the mudlib programmer to alter this behavior
> > except to have compile_object() be redefined and call some function
> > in any non-clone object it compiles. Would there be a Bad side
> > effect if I did that?

If it suits you, there should be no problem with that.
I guess I'll implement the same thing myself.

> 
> It would in many many cases be entirely unnecesary.  For instance for
> objects that are only used to make clones of, or to inherit, the usual
> ones for rooms and treasure-objects, or whatever.

I can't really see it nescessary in _any_ circumstance. Please name one.
Of course it is perhaps better to support it than not support it at all.
But why just for master objects, why not for clones too? I suspect the
answer has something to do with DGD-Internals...

> 
> Hope this helped,
> 
> Erwin.
> 


PS. I ALWAYS test things before making assumptions about things, never
trusting documentation or others arguments. It is essential to know _all_
the details and see for yourself.


Keep on DGD-ing!

Frank Schmidt


Date: Thu, 11 Jun 1998 11:59:27 +0200 (MET DST)
From: "E. Harte"
Subject: [DGD] Re: Couple DGD questions

On Wed, 10 Jun 1998, Frank Schmidt wrote:

[...]
> Functions which you call with call_out() in DGD may be static and/or
> private, as with most functions called directly from the dgd driver. Makes
> security for the driver object, user object and call_outs very simple; by
> use of static.

Functions called from DGD itself may not be private, only static (or no
additional restrictions at all, of course).  That goes for functions
called in the driver-object as well as functions called by the call_out()
kfun.

[...]
> Only previous_object() check is nescessary to see if it was called
> directly from the driver, and the driver alone (e.g. call_out).
> Previous_object() will return 0 if the call was a call_out() or similar
> call.

Uhm, no.  But if you replace previous_object() with previous_program()
then your claim becomes truth.  The problem with previous_object() is that
it'll be 0 when the calloutfunction (__heart_beat() or whatever) is called
directly, without call_other(), from for instance another call_out().

    
Erwin.



From felix Fri Jun 12 18:37:34 1998
Subject: Re: [DGD] Re: Couple DGD questions

E. Harte wrote:

> On Wed, 10 Jun 1998, Frank Schmidt wrote:
>
> [...]
> > In the auto object, a static function behaves like a kernel function
> > (kfun) _too_: It cannot be accessed by call_other(this_object(),
> > "kfun_func"), _and_ calls to it in the auto object are _not_ redirected
> > to any masked function in this_object(). This is true for ALL static
> > functionnames in the auto object, not just the default functions
> > specified by the driver you happen to override.
>
> I'd like to have confirmation or denial of the last part from Dworkin, as
> most definitely remember there being a difference between using a 'pure'
> kfun in the auto-object and a static function that happened to be defined
> in the auto-object.

Frank is correct.  To be yet more precise: <any> calls made to static
functions in the auto object can never be redirected to a new function
by masking the static function, no matter from where the calls are
made.  In C++ terminology, static functions in the auto object are
not "virtual".


> [...]
> > > <auto-object>
> > > static int
> > > valid_write(string filename)
> > > {
> > > }
> > > 
> > > static void
> > > write_file(string filename)
> > > {
> > > }
> > > </auto-object>
> > > 
> > > <other-object>
> > > static int
> > > valid_write(string filename)
> > > {
> > >     return 1; /* of course ;) */
> > > }
> > > </other-object>
> > 
> > No, sorry, but this will not disable his security IF the security call is
> > made in the auto object, but it will override the call made in an
> > inherited program.
>
> Oh?  Again, I'd like confirmation of this.  (Or else I'll go check the
> sources myself this weekend. *grin*)

Again, Frank is correct.  Calls made to valid_write() from any object
in the inheritance chain between the auto object and other-object
will continue to use the auto object version of the function.

Dworkin


From felix Fri Jun 12 18:40:18 1998
Subject: Re: [DGD] Re: Couple DGD questions

E. Harte wrote:

> On Wed, 10 Jun 1998, Frank Schmidt wrote:
>
> [...]
> > Functions which you call with call_out() in DGD may be static and/or
> > private, as with most functions called directly from the dgd driver. Makes
> > security for the driver object, user object and call_outs very simple; by
> > use of static.
>
> Functions called from DGD itself may not be private, only static (or no
> additional restrictions at all, of course).  That goes for functions
> called in the driver-object as well as functions called by the call_out()
> kfun.

They cannot be private; note that they can also not be static in the
auto object.

Dworkin


From felix Fri Jun 12 19:26:06 1998
Subject: Re: [DGD] Re: Couple DGD questions

Stephen Schmidt wrote:

> On Fri, 12 Jun 1998, Felix A. Croes wrote:
> > To be yet more precise: <any> calls made to static
> > functions in the auto object can never be redirected to a new function
> > by masking the static function, no matter from where the calls are
> > made.  In C++ terminology, static functions in the auto object are
> > not "virtual".
>  
> To put this in language "for the rest of us" :)  this means that
> in the auto object, "static nomask" is redundant?

Not exactly.  I think you are confused about the meaning of "nomask":
a static function in the auto object <can> be masked, it just doesn't have
any effect on existing calls to that function.  Declaring it to be nomask
would make masking it impossible: attempting to do so would result in a
compile-time error.

Dworkin



Date: Mon, 30 Nov 1998 14:50:51 +0100 (MET)
From: Mikael Lind
Subject: Re: [DGD]varargs void foo(object bar)

On Mon, 30 Nov 1998, Frank Schmidt wrote:

> [...]
> 
> My problem: varargs with objects as parameters, and dealing with default
> values for objects.
> 
> Example: varargs void foo(object bar)
> 
> Now the call to this function can happen in four different scenarios:
> 1) foo()
> 2) foo(beer) /* when <beer> != 0 */
> 3) foo(beer) /* when <beer> == 0 */
> 4) foo(0)
> 
> The problem in this example is that there is absolutely NO way in foo()
> to detect that <bar> is a default parameter set-to-0 in 1). E.g.
> according to the tracelist, scenario 1), 3) and 4) are identical.

Use ellipsis, the "..." operator. This is will convert an argument list to
an array or vice versa, depending on the context.

varargs void foo(object bar...) {
    /* "bar" is an object array that is now containing all arguments
       supplied */

    int size;

    size = sizeof(bar);
    if (size > 1) {
        /* too many arguments supplied */

    } else if (size == 0) {
        /* scenario 1 */

    } else if (bar[0] != 0) {
        /* scenario 2 */

    } else {
        /* scenario 3 or 4 */

    }
}

As far as I know, it's currently impossible to distinguish scenario 3 from
scenario 4 from within the LPCd code. (And I don't see why you'd want to.)

There's certainly more to say about the design issue of giving a function
several different functionalities. Sometimes, it's more useful to split
the function into two (or even more) functions: 

void foo1(object bar) {
    if (bar == 0) {
        /*
         * scenario 3 or 4; in some cases considered an incorrect call, in
         * some other cases a default value could be assumed, and in still
         * other cases nothing is known for sure ;)
         */

    } else {
        /* scenario 2 */

    }
}

void foo2() {
    /* scenario 1 */

}

It all depends on what it is that you want to do.

[Insert a lengthy discussion on the benefits of argument-based function
call binding here, if you find it at all necessary.]

// Mikael



Date: Sun, 10 Jun 2001 23:57:41 -0400
From: Kris Van Hees
Subject: Re: [DGD]Scope (::) operator and Kernel lib wiztool

Functions called with the :: scope prefix call a function in the inherited
objects, and because of the multiple inheritance implementation it is known
that exactly one function with a given name will be visible to the calling
code.  If the auto object defines the functions and no other inherited class
that's interposed between the auto object and your object redefines it, then
it will be calling the function in the auto object of course.

	Kris

On Sun, Jun 10, 2001 at 08:47:35PM -0700, Noah Lee Gibbs wrote:
>   I've got a lightly-customized Kernel lib up and running and I'm playing
> around with the code in different ways.  Got a DGD LPC question.
>   I remember from the archives that the two-colon scope operator, ::, is
> used to call a kfun or (same thing, mostly) a static function in the auto
> object.  But in /kernel/obj/wiztool's create() function, it appears to be
> calling to its parent (/kernel/lib/wiztool) with the same syntax -- if it
> called straight up to auto, it would just say ::create(1) to say that it
> was a clone (and it isn't) instead of saying ::create(200) to set hsize to
> 200.
>   Does anybody know if this is just a bug in the Kernel lib or if
> functions called with the scope operator call to the parent before trying
> the auto object?
> 
> 

-- 
Software Developer & Creator of Worlds


From: Par Winzell
Date: Fri, 22 Jun 2001 19:58:44 -0700
Subject: Re: [DGD]Arrays and call others

 > I'm a little worried that making call others each time will be eating up
 > memory. Would it be better to make one call other setting arrays in the
 > function: 
 > 
 > (2)
 > 
 > Rnames = current_object->query_reference_names();
 > 
 > for (i = 0, sz = sizeof(rnames); i < sz; i++)
 > {
 >     if (rnames[i] == name_test)
 >     {
 >         return current_object;
 >     }              
 > }    


In practice, the time consumed by the call-other itself is probably
not such a big deal. But it's typically a good idea to store return
values in a variable, yes, especially if you do not have absolute
control over what may happen inside query_reference_names() in the
future. Maybe somebody will change its internal implementation in
such a way that it becomes a backwards compatiblity function going
at some sluggish pace? I've seen it happen.

You can obfuscate your code quite a bit if you like it small:

	if (sizeof(current_object->query_reference_names() &
                   ({ name_test })) != 0) {
		return current_object;
	}


Zell



From DGD Mailing List  Sat Oct 27 13:10:01 2001
From: DGD Mailing List (Erwin Harte)
Date: Sat Oct 27 13:10:01 2001
Subject: [DGD] Another question from the DGD n00b...

On Sat, Oct 27, 2001 at 07:57:22PM +0200, Troels Therkelsen wrote:
> Hi all,
> 
> I was wondering why the backend (call_out(), creator function, etc)
> can't call static functions in the auto object?
> 
> I mean, it's fully within the logic of the static modifier that
> other LPC objects can't call the function.  But in all other
> objects (programs, I guess it is?) than the auto object/program,
> the backend is perfectly capable of calling static functions.

That's because in all other objects, static functions are just that,
static functions, but if you define a function as static in the auto-
object, you tell DGD that this is a special function, an afun or efun
if you will, and one of the side-effects is that you cannot call it
with a call_other() anymore, just like you can't do that for the built
in kfuns.

Erwin.
-- 
Erwin Harte


From DGD Mailing List  Sun May 25 05:48:01 2003
From: DGD Mailing List (Felix A. Croes)
Date: Sun May 25 05:48:01 2003
Subject: [DGD] Auto and Driver objects

"Ben Chambers" wrote:

>[...]
> Then to make a specific backpack or something I would want to inherit both
> the base object and the container object, but with the container object's
> versions of move from and move into overriding the versions defined in the
> base object.  Would this be possible?  Basically, the base version provides
> the default 'You can't move that from that to that' behavior, while the
> container provides the you can move it, and the end object is the specific
> version of how this is done.

By inheriting from two different objects that both define the same
function, you introduce a conflict.  That conflict must be resolved by
masking the function in the inheriting object, like this:

    inherit base "/foo/bar/base";
    inherit container "/foo/bar/container";

    int MoveInto(object item)
    {
	return container::MoveInto(item);
    }

    int MoveFrom(object item)
    {
	return container::MoveFrom(item);
    }

There are other ways in which this issue can be addressed.  For instance,
the container object could be made to inherit the base object, in which
case its functions would automatically override those of the base object.
Should another object then inherit both, the compiler will understand
that the container functions are meant to mask those of the base object,
and no conflict will ensue.

Regards,
Dworkin



From DGD Mailing List  Thu Feb 12 15:13:06 2004
From: DGD Mailing List (Robert Forshaw)
Date: Thu Feb 12 15:13:06 2004
Subject: [DGD] My idea for the DGD driver - validate

In my mudlib I have an object daemon, and it is responsible for just about 
everything regarding objects, from keeping track of inheritance to 
monitoring players idle status. There are many functions in my object daemon 
that I don't want just any object to call. In fact, just about any function 
that doesn't begin with 'query_' has some validation code at the beginning. 
I also developed a function called alert, which is kind of like a runtime 
error but noisier and is executed when an object tries to do something it 
shouldn't be doing (it sends a notification message to any admin that is 
logged in, for instance). So when naughty_object does OBJECTD -> 
hazardous_function(), hazardous_function() performs some checks on what the 
previous_object() or previous_program() was, and calls alert() if necessary 
and then error() to abort execution.

This method became rather heavy-handed, so I eventually decided to have a 
seperate function called verify_object_daemon_function_call (the name isn't 
important). Basically, all other functions that need security are declared 
private, and any object wanting to access any of those functions must call 
vodfc() first. e.g. OBJECTD -> vodfc(some_function, mixed args...)

This is so ugly though, that I hit upon the idea of having such a thing 
built in the driver. It would then be much easier to implent security of the 
nature I've described into an object.

The idea is that there would be a keyword, for example, validate, for a 
function. Any function declared with this keyword can not be called by 
anything except the driver. Now, when naughty_object does a call_other to 
OBJECTD, or whatever, if there is a validate function there then that 
function will be called instead of the function specified. If the function 
bearing the validate keyword returns zero,

To put that in code, lets say that we have:

/* naughty_object.c */


string mysterious_function()
{
  OBJECTD -> hazardous_function();
  return "";
}

/* EOF */


and then, in object_daemon.c:

/* object_daemon.c */

validate int security_function(string func_name, mixed args...)
{
  switch(func_name)
  {
    case "hazardous_function":
      if(previous_object() == naughty_object())
      {
        alert("Uh-oh, naughty_object() tried to call hazardous_function, 
call the cops!!");
        return 0;
      }
    default: return 1;
  }
  return 1;
}

string * hazardous_function()
{
  /* do something hazardous */
  return 0;
}

Here's what I propose the advantages and disadvantages to be of this method:

Advantages:

1) It makes an object far more resilient than it could be using any current 
available feature of the driver. If a function exists in an object with the 
'validate' keyword, it has many security implications for the object. There 
is no way on earth that any function can be called in that object by another 
object(except the driver of course), without calling the function bearing 
the 'validate' keyword first. Thus, there is no need to declare any 
functions as private.

2) It makes it impossible to expose a security hole even if you're the 
dopiest programmer on earth. There is no oppertunity for forgetting to 
insert a security check into every single function that you want protected. 
All security checks are condensed down to one function and so there is only 
one place to look when you need to maintain that security.

3) It saves having to type many lines of code, and much simplifies the 
process of implenting call_other security.

4) It saves ticks.

5) As an extention of the idea, it could be possible to have several 
functions with the 'validate' keyword, which are called in succession until 
one of them eventually returns 0 (stop execution) or they all return 1 
(function is called as normal, as if it were called directly via 
call_other() in lieu of current behaviour.

Disadvantages:

1) It transgresses the 'philosophy' of DGD that if a feature can be 
implented in the lib rather than the driver, it should be. I personally 
don't consider this valid in this case as I'd colligate it with the hallmark 
functions that make DGD driver to be reckoned with, like atomic functions. 
Okay, so atomic function behaviour can't be implented solely in the lib, and 
my idea can, to a degree. But not to such bullet-proof perfection. Doing it 
the mudlib is far messier and far more prone to security holes.

That's it. Tell me what you think!

_________________________________________________________________
Express yourself with cool new emoticons http://www.msn.co.uk/specials/myemo



From DGD Mailing List  Thu Feb 12 15:24:04 2004
From: DGD Mailing List (Robert Forshaw)
Date: Thu Feb 12 15:24:04 2004
Subject: [DGD] My idea for the DGD driver - validate

Something I forget to mention:

the 'validate' function will return zero by default. Therefore, any function 
that needs call_other permission has to be deliberately given it. And you 
can do 'validate validate_func() { }' to immediately isolate your object 
from call_other's. This makes it very hard to accidently give access to an 
object that you didn't mean to.

_________________________________________________________________
It's fast, it's easy and it's free. Get MSN Messenger today! 
http://www.msn.co.uk/messenger


From DGD Mailing List  Thu Feb 12 15:27:01 2004
From: DGD Mailing List (Robert Forshaw)
Date: Thu Feb 12 15:27:01 2004
Subject: [DGD] My idea for the DGD driver - validate

And here is an amendment to the following paragraph of my original post, 
which became truncated for some reason:

The idea is that there would be a keyword, for example, validate, for a 
function. Any function declared with this keyword can not be called by 
anything except the driver. Now, when naughty_object does a call_other to 
OBJECTD, or whatever, if there is a validate function there then that 
function will be called instead of the function specified. If the function 
bearing the validate keyword returns zero, the execution halts and the 
function that was the first argument of call_other is never called. If one 
is returned, execution may continue as normal and the function that was the 
first argument of call_other is called normally and transparently.

_________________________________________________________________
Express yourself with cool new emoticons http://www.msn.co.uk/specials/myemo


From DGD Mailing List  Thu Feb 12 15:30:01 2004
From: DGD Mailing List (Erwin Harte)
Date: Thu Feb 12 15:30:01 2004
Subject: [DGD] Re: My idea for the DGD driver - validate

On Thu, Feb 12, 2004 at 09:12:52PM +0000, Robert Forshaw wrote:
[...]
> The idea is that there would be a keyword, for example, validate, for a 
> function. Any function declared with this keyword can not be called by 
> anything except the driver. Now, when naughty_object does a call_other to 
> OBJECTD, or whatever, if there is a validate function there then that 
> function will be called instead of the function specified. If the function 
> bearing the validate keyword returns zero,

Perhaps you've noticed 'private' and 'static' functions in other code?
I believe these will allow you to do 99% of what you want, already.

A private function is only callable from within the program where it
was implemented.  Even code inheriting it cannot access the function,
similar to how private variable are not visible to inheriting code.

A static function is only callable from within the object that it's
in.  Code inheriting the program that it was in can also use it but
you cannot access it from another object.

Hope that helps,

Erwin.
-- 
Erwin Harte

From DGD Mailing List  Thu Feb 12 15:43:01 2004
From: DGD Mailing List (Robert Forshaw)
Date: Thu Feb 12 15:43:01 2004
Subject: [DGD] Re: My idea for the DGD driver - validate

>From: Erwin Harte
> > The idea is that there would be a keyword, for example, validate, for a
> > function. Any function declared with this keyword can not be called by
> > anything except the driver. Now, when naughty_object does a call_other 
>to
> > OBJECTD, or whatever, if there is a validate function there then that
> > function will be called instead of the function specified. If the 
>function
> > bearing the validate keyword returns zero,
>
>Perhaps you've noticed 'private' and 'static' functions in other code?
>I believe these will allow you to do 99% of what you want, already.

You would know that I have if you read the entire post, as I mention these 
keywords. You would also know that 99% of what I want cannot be fulfilled by 
'private' and 'static'. There is far more to my idea than simply privatising 
a function, or all functions. The feature is supposed to allow you to decide 
what objects can call the functions in an object, (or you can in fact decide 
whether the functions can be called on any expression, its entirely up to 
you what goes in the validate function) in a very compact way, without the 
need to perform individual checks at the beginning of each and every 
function, which is both tedious and prone to human error.

So instead, these checks are implented in one function that the driver 
dictates is manditory to be called whenever a call_other is called with that 
object as the first argument. 'private' and 'static' are absolutes, because 
they either say 'you can call this function from another object' or 'you 
can't call this function from another object'. My 'validate' idea allows for 
far more flexibility; it says 'You can't call a function in this object from 
another object unless I say so by returning 1, and by default, I won't 
return 1, so you MUST lay down the necessary security measures in here or 
I'll return 0 and you can't call anything in this object from a different 
object!'. As you can see, it's a very different thing.

The reason I described my current problem at the beginning of my post was so 
that you would appreciate that this feature is about letting very particular 
objects execute a function, or execute it under very particular conditions. 
None of which can be achieved using 'static' or 'private' whatsoever. 
Ideally, a security-conscious lib coder would use 'validate' in every object 
that contains functions that they don't want 'just any object' to call, but 
can't be private or static either.

_________________________________________________________________
Express yourself with cool new emoticons http://www.msn.co.uk/specials/myemo


From DGD Mailing List  Thu Feb 12 15:57:01 2004
From: DGD Mailing List (Steve Foley)
Date: Thu Feb 12 15:57:01 2004
Subject: [DGD] Re: My idea for the DGD driver - validate

> a function, or all functions. The feature is supposed to allow you to
decide
> what objects can call the functions in an object, (or you can in fact
decide
> whether the functions can be called on any expression, its entirely up to
> you what goes in the validate function) in a very compact way, without
the
> need to perform individual checks at the beginning of each and every
> function, which is both tedious and prone to human error.

Couldn't you override call_other in the AUTO to call this security function
of yours and get the same result?  Granted, you'd need to write that
validate function in each object, and you'd be imposing a small cost on all
call_others (the large majority of which likely won't be giving rise to
security concerns), but this would meet your requirements, wouldn't it?


From DGD Mailing List  Thu Feb 12 16:14:01 2004
From: DGD Mailing List (Robert Forshaw)
Date: Thu Feb 12 16:14:01 2004
Subject: [DGD] Re: My idea for the DGD driver - validate

>From: "Steve Foley"
>Couldn't you override call_other in the AUTO to call this security function
>of yours and get the same result?  Granted, you'd need to write that
>validate function in each object, and you'd be imposing a small cost on all
>call_others (the large majority of which likely won't be giving rise to
>security concerns), but this would meet your requirements, wouldn't it?

I hadn't thought of this so thanks for pointing it out. I'll give it a try 
and see how it works out. Incidently, by using function_name() in the 
override function I could detect whether the validate function is there or 
not, and it wouldn't be necessary to declare the validate function in each 
object. I still think my idea would be more convenient, but its probably too 
much work to implent to justify the benefits... One thing though, will 
overriding call_other also apply to the -> operator?

_________________________________________________________________
Express yourself with cool emoticons - download MSN Messenger today! 
http://www.msn.co.uk/messenger


From DGD Mailing List  Thu Feb 12 16:25:02 2004
From: DGD Mailing List
Date: Thu Feb 12 16:25:02 2004
Subject: [DGD] Re: My idea for the DGD driver - validate

The call_other() override in AUTO, combinded with a function_object()call
to see if the validate() function existed (default if not: allow the call)
would save a lot of coding for routine objects.  Validate() would then
only need to be added to sensitive objects.

I might be missing something, but seems like you could get 100% of what
you want using the above.

Kevin C.



From DGD Mailing List  Thu Feb 12 16:32:01 2004
From: DGD Mailing List (Steve Foley)
Date: Thu Feb 12 16:32:01 2004
Subject: [DGD] Re: My idea for the DGD driver - validate

> and see how it works out. Incidently, by using function_name() in the
> override function I could detect whether the validate function is there or
> not, and it wouldn't be necessary to declare the validate function in each
> object. I still think my idea would be more convenient, but its probably too
> much work to implent to justify the benefits... One thing though, will
> overriding call_other also apply to the -> operator?

Well, you could also leave the auto_object empty and use multiple auto objects
as well (via the path_include trick discussed elsewhere) potentially.  The
assumption there being that the two kinds of objects (those that need this kind
of security and those that don't) will likely be in different parts of your
directory structure.  You'd just have to be sure to declare it static and
nomask, and I think that would make it function similarly to a static function
declared in the AUTO.

As for ->, yes.  Overriding call_other has that effect.  -> is just a macro for
call_other.


From DGD Mailing List  Thu Feb 12 18:49:00 2004
From: DGD Mailing List (Michael McKiel)
Date: Thu Feb 12 18:49:00 2004
Subject: [DGD] Re: My idea for the DGD driver - validate

Not going to quote anything specific here... 
But couldn't this functionality be done by a mapping of a given object and
certain security conscious functions within that object ...
ie the mapping would be on the object_file_name and the function in question,
and contain what is allowed to call it.

and the function itself would just start with:

if (!validate(previous_object()) return [0|nil];
or optionally do some logging/warnings:
if (!validate(previous_object()) { alert(previous_object()); return [0|nil];



______________________________________________________________________ 
Post your free ad now! http://personals.yahoo.ca

From DGD Mailing List  Thu Feb 12 18:58:01 2004
From: DGD Mailing List (Robert Forshaw)
Date: Thu Feb 12 18:58:01 2004
Subject: [DGD] Re: My idea for the DGD driver - validate

>"Robert Forshaw" wrote:
>
> > >From: Erwin Harte
> > >Perhaps you've noticed 'private' and 'static' functions in other code?
> > >I believe these will allow you to do 99% of what you want, already.
> >
> > You would know that I have if you read the entire post, as I mention 
>these
> > keywords. You would also know that 99% of what I want cannot be 
>fulfilled by
> > 'private' and 'static'.
>
>I read your postings, and I do not see you refer to static functions
>anywhere.  Perhaps that bit was also mysteriously omitted?  After
>reading them as they were posted, the assumption that you didn't know
>about static functions is not unreasonable.

Then we have a difference of opinion. Being ignorant of static and not of 
private seems very unlikely to me. I thought it would be obvious from my 
posts that I'm not so inept as to not know what they are. As to the 'static' 
being ommited, yes I didn't mention static. I thought I had. Not that it 
matters, since none of it was really applicable to my post.

>
>Regarding calling security, I think one mistake was made during the
>inception of LPC: functions (and variables) should be private by
>default.  Unfortunately it is now too late to change this.

This would of course require the inclusion of 'public' (like other drivers 
seem to possess, but dgd doesn't...).

>
>By masking call_other(), you are making things needlessly complex.

How come? I thought it was a good point that kevinc/Steve Foley mentioned. 
While I definitely would not say no to my validate idea being included in 
DGD, as it would make the solution even easier to implent and would be less 
costly, the feature can still be achieved by masking call_other can it not? 
Here's what my masking function looks like:

mixed call_other(mixed obj, string function, mixed args...)
{
    if(function_object("verify_call_other", find_object(obj)))
          if(!::call_other(obj, "verify_call_other", function, args))
                return nil;

    return ::call_other(obj, function, args...);
}
I
>suspect that you may still not quite get the effect you are looking
>for.  Personally, I like the validate(); idea.

Could you explain what unexpected effects I have missed? I'm glad you liked 
the idea. Is it useful enough to be included in the source?

_________________________________________________________________
Express yourself with cool new emoticons http://www.msn.co.uk/specials/myemo


From DGD Mailing List  Thu Feb 12 19:08:01 2004
From: DGD Mailing List (Robert Forshaw)
Date: Thu Feb 12 19:08:01 2004
Subject: [DGD] Re: My idea for the DGD driver - validate

>From: Michael McKiel
>Not going to quote anything specific here...
>But couldn't this functionality be done by a mapping of a given object and
>certain security conscious functions within that object ...
>ie the mapping would be on the object_file_name and the function in 
>question,
>and contain what is allowed to call it.
>
>and the function itself would just start with:
>
>if (!validate(previous_object()) return [0|nil];
>or optionally do some logging/warnings:
>if (!validate(previous_object()) { alert(previous_object()); return 
>[0|nil];

Can you index nil on an array..? Anyway, the idea seems workable, but the 
feature I had in mind would be at a more fundamental level, to be implented 
by whoever is coding the lib itself. The idea you are suggesting uses 
variables to determine security, and the only reason to have it in variables 
would be to allow other people to come along and set the security with some 
abstract function (like one sets the daemons in the kernel lib). Its akin to 
the idea of not exposing people to the complicated 'innards' of the driver, 
and instead have them only required to know a simpler set of functions that 
modify a simpler set of variables (although I find the issue of security to 
be anything but simple, and if you're targetting mediocre coders who just 
want to be able to set variables via a function, the security should already 
be implented in the lib to avoid such a feature being necessary).
Therefore, while I don't find anything particularly wrong with your idea, 
its a totally different thing to what I had in mind as its at a higher 
level.

_________________________________________________________________
Find a cheaper internet access deal - choose one to suit you. 
http://www.msn.co.uk/internetaccess


From DGD Mailing List  Fri Feb 13 09:13:01 2004
From: DGD Mailing List (Robert Forshaw)
Date: Fri Feb 13 09:13:01 2004
Subject: [DGD] Re: My idea for the DGD driver - validate

> > >By masking call_other(), you are making things needlessly complex.
> >
> > How come?
>
>It is hard to be more specific since I have only a vague notion of
>what you are trying to accomplish.  I have noticed a tendency among
>people who have just discovered that call_other() can be masked, to
>consider it the solution to everything.  So, broadly stated, I hope
>that you will reconsider other ideas, should you come to the
>conclusion that redefining call_other() does not suffice.

What I am trying to ultimately accomplish is to have checks performed before 
various functions in an object are allowed to continue execution, to ensure 
that only the right objects are able to call it. My validate() idea, as you 
called it, was sufficient for this except for two things: it was more prone 
to error (i.e. it is in theory possible to still call a function that you 
aren't meant to), and the alternative way I came up with is even easier to 
implent. Because the 'validate' idea I had (and subsequently, the masking 
idea that was suggested) involves a manditory function call that will 
dissallow every call_other by default, it is much more difficult to make a 
security gap as a result of human error, and it isn't necessary to go adding 
code to the beginning of every function you want protected. I appreciate 
what you were saying about people mistakenly seeing masking call_other as a 
be-all-end-all solution, but in this particular case, I think it's a very 
good solution and I don't foresee any problems with it except for the 
additional overhead, which is minor. I will of course post an update if it 
doesn't work out how I expect it to. :)

_________________________________________________________________
Express yourself with cool new emoticons http://www.msn.co.uk/specials/myemo



From DGD Mailing List  Sat Feb 21 09:37:01 2004
From: DGD Mailing List (Erwin Harte)
Date: Sat Feb 21 09:37:01 2004
Subject: [DGD] Re: varargs int ...

On Sat, Feb 21, 2004 at 03:04:16AM -0500, Michael McKiel wrote:
> Is it possible to test if a varargs int parameter was passed to a given
> function or not?
> I was playing around with a strstr() function, and seems I want to make it
> work differently if the 2nd int variable wasn't passed ie:
> string strstr(string str, int start, varargs int end) {
> 
> if I don't pass it 'end' then the function should assume end = strlen(str)-1
> if I pass it end == 0, then it should return a nil string, since it would be
> a zero length string.
> But it seems all I can test for is !end
> and that is true if I don't pass an end variable, and IF I pass it 0...
> 
> So what am I missing?

The only way I can see to be 100% sure what parameters were provided
or not, is by using the ellipsis:

    string strstr(string str, int start, varargs mixed extra...) {
        int end;

        if (sizeof(extra) == 0) {
            /* No extra parameters provided. */
        } else if (sizeof(extra) == 1 && typeof(extra[0]) == T_INT) {
            /* Extra parameter was provided and was an integer. */
            end = extra[0];
        } else {
            error("bad argument 3 to strstr");
        }
        ...
    }

The next best thing is:

    string strstr(string str, int start, varargs mixed end) {
        if (end == nil) {
            /* Varargs parameter omitted or 'nil' value used. */
        } else if (typeof(end) == T_INT) {
            /* Extra parameter provided and was an integer. */
        } else {
            error("bad argument 3 to strstr");
        }
        ...
    }

But then you can't distinguish between strstr("foo", 1, nil) and
strstr("foo", 1).

If you don't care about that distinction, then by all means go ahead
and use that approach. ;-)

Hope that helps,

Erwin.
-- 
Erwin Harte



From DGD Mailing List  Sat Aug 28 11:08:01 2004
From: DGD Mailing List (Steve Wooster)
Date: Sat Aug 28 11:08:01 2004
Subject: [DGD] Making my own function types

At 07:48 AM 8/25/2004, you wrote:
>Is there any function type that doesn't do anything special?
>I've built a permission system and I want to be able to specify what
>functions that can't be called by all objects, without having to create a
>database of those functions.
>Is there any way to check what type a function is?
>
>Regards,
>Ludvig Lejon

I don't know if this would be acceptable to you, but here's an idea...
You could set it up, so that functions who's names start with _ (or secure_ 
or something else) require some kind of security check. EG, something like:

void myfunc()
{
     code;
}

void _myfunc()
{
     code;
}

int valid_call( string funcname, object caller )
{
     return 1 or 0;
}

"myfunc" could be called without security restrictions, but "_myfunc" would 
need valid_call() to return 1. Of course, maybe instead of having a 
valid_call function in the object, you could put it in the master object or 
a security daemon.

A way to do this might be: When an object is loaded, check through its 
function listing for functions who's names start with _. If an object has 
some, then call call_touch() in the object. When touch() is called in the 
driver, check if the function call starts with _, and if it does, call 
valid_call() in the object (or security daemon or whatever) to see if it's 
allowed. If it's not, then do error("You're not allowed to do that, you 
evil exploit-abuser! Go away! Shoo! Shoo!"). In any case, be sure to do 
call_touch() in the object again.

I figure that's probably more efficient than masking call_other, since 
masking call_other will affect the performance of objects that don't care 
about security (which I presume are the majority). Unfortunately, I'm a 
newbie to DGD, so I don't know if this is the best way to do security. 
Hopefully somebody knowledgeable can back up or shoot down this idea.

-Steve Wooster