Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Securing Prolog database

3 views
Skip to first unread message

Mauro DiNuzzo

unread,
Feb 1, 2010, 7:19:15 PM2/1/10
to
Hi all,

Does anybody know if a sort of SQL-like security of Prolog database has been
ever implemented somehow?

As I am interested in "Prolog and the Web", I argue that securing of
modules/predicates is mandatory.
I guess that this would be reasonably easy to implement for Prolog systems
developers.

As a starting point, I think that a simple hook into prolog calls (i.e. the
possibility to intercept *any* call) should be enough to implement
assert/retract as well as call permissions.

Any insight?


Thank you very much.

M

Jan Wielemaker

unread,
Feb 2, 2010, 3:35:16 AM2/2/10
to

I'm working with Torbjorn Lager on a thing called SWAPP. In a
nutshell, the idea is to provide a RESTful API to Prolog where the
user can post logical theories (Prolog programs) and query them. The
result is sent as JSON.

We solve the security by analysing the possible call-tree and checking
that against a white-list.

Intercepting all calls is possible in SWI-Prolog by means of the tracer
hook, but you probably get better results doing full meta-interpretation.
Program analysis of course also costs time, but at least doesn't affect
runtime and the results can be cached (not implemented yet).

The current state (though far from complete and surely the safety needs
more checking and thought) is at

http://www.swi-prolog.org/git/contrib/SWAPP.git

(requires the current GIT version of SWI-Prolog 5.9.8 due to a mistake
in the predicate-property declaration for retract/1 in older versions.
Older versions consider retract/1 always unsafe, while we consider it
safe if we can prove that the argument is not module-qualified and
therefore does not retract outside the current module).

Cheers --- Jan

Paulo Moura

unread,
Feb 2, 2010, 7:46:39 AM2/2/10
to
On Feb 2, 12:19 am, "Mauro DiNuzzo" <pico...@alice.it> wrote:
> Hi all,
>
> Does anybody know if a sort of SQL-like security of Prolog database has been
> ever implemented somehow?
>
> As I am interested in "Prolog and the Web", I argue that securing of
> modules/predicates is mandatory.

Logtalk, which you can run with most Prolog compilers, enforces
predicate scope directives (predicates can be declared public,
protected, or private) and provides a secure implementation of meta-
predicates.

> I guess that this would be reasonably easy to implement for Prolog systems
> developers.

Easy, yes. The problem is that most Prolog implementers don't want to
break compatibility with existing code.

> As a starting point, I think that a simple hook into prolog calls (i.e. the
> possibility to intercept *any* call) should be enough to implement
> assert/retract as well as call permissions.
>
> Any insight?

As Jan suggested, you can define a meta-predicate that takes as
argument a call and meta-interprets it in order to check is safety.

Cheers,

Paulo


Mauro DiNuzzo

unread,
Feb 2, 2010, 8:22:53 AM2/2/10
to
Thank you Jan and Paulo,

actually I was thinking to a sort of user-dependent privileges on Prolog
database.
As a very simple sketch, you can consider a user/4 predicate:

user(ID, Password, ARPrivileges, CPrivileges)

where ARPrivileges means assert/retract permission, while CPrivileges means
call permission.
Privileges could be a list of Module:Functor/Arity elements. For example:

[_:_/_] would mean full "admin"
[lists:_/_, user:_/_] would mean the user is allowed to call
every predicate of modules "lists" and "user"

or anything more complex such as:

[lists:P], memberchk(P, [permutation/2, union/3]), ...


Does this make any sense?

Thank you again.


M

Jan Wielemaker

unread,
Feb 2, 2010, 9:14:34 AM2/2/10
to
On 2010-02-02, Mauro DiNuzzo <pic...@alice.it> wrote:

I guess yes, but a runtime check of such a flexible scenario would be a
bit slow. Making a few restrictions on the language and find out the
permissions before you do any calling looks more promising. That is why
I wrote safe_goal(:Goal). The current implementation refuses if it finds
a meta-call for which it cannot figure out what will be called. You
could of course replace call(X) by safe_call(X) in that case and
implement safe_call/1 as:

safe_call(Goal) :-
( safe_goal(Goal)
-> call(Goal)
; permission_error(call, goal, Goal)
).

and likewise for call/2-, assert/1, etc.

Changing the simple safe_goal/1 which is simply based on a white-list
of goals to use a white-list for the current user profile is a simple
change. You can even do (in the current code-base):

save_primitive(assert(_)) :- privileges(admin).

Join the club if you want to break the current safe_goal approach or
want to extend it with facilities you propose.

Cheers --- Jan

Mauro DiNuzzo

unread,
Feb 2, 2010, 10:07:20 AM2/2/10
to
It would be very nice to have user privileges in the Prolog engine proper
(see later).
I was thinking of a things much like to SQL privileges. Translating
brutally, it may requires only two new directives like:

1) grant(+Privilege, +To, +On)

Just to give a couple of example:

:- grant(assert, mauro, [user:p/1, user:q/1]).

or:

:- grant(call, public, [system:_]).

Obviously, one should implement also:

2) revoke(+Privilege, +On, +From)

With respect to the checking process, I argue that it would be fruitful to
implement in the interpreter proper. I don't know exactly how (perhaps you
do), but I was thinking to a sort of hidden goals which are automatically
(i.e. transparently to the user) incorporated into every predicate. For
example:

assert(Module:Term) :- current_user(User), current_privilege(assert, User,
P), ... % checking on module/predicate

In other words, do you think that the problem can be solved by means of
external library, or one has to act inside the engine (i.e.
interpreter/compiler) proper?

Thank you.


M


"Jan Wielemaker" <ja...@hppc323.few.vu.nl> wrote in message
news:slrnhmgck...@hppc323.few.vu.nl...

Jan Wielemaker

unread,
Feb 2, 2010, 10:18:40 AM2/2/10
to
On 2010-02-02, Mauro DiNuzzo <pic...@alice.it> wrote:
> It would be very nice to have user privileges in the Prolog engine proper
> (see later).
> I was thinking of a things much like to SQL privileges. Translating
> brutally, it may requires only two new directives like:
>
> 1) grant(+Privilege, +To, +On)
>
> Just to give a couple of example:
>
> :- grant(assert, mauro, [user:p/1, user:q/1]).
>
> or:
>
> :- grant(call, public, [system:_]).
>
> Obviously, one should implement also:
>
> 2) revoke(+Privilege, +On, +From)
>
> With respect to the checking process, I argue that it would be fruitful to
> implement in the interpreter proper. I don't know exactly how (perhaps you
> do), but I was thinking to a sort of hidden goals which are automatically
> (i.e. transparently to the user) incorporated into every predicate. For
> example:
>
> assert(Module:Term) :- current_user(User), current_privilege(assert, User,
> P), ... % checking on module/predicate
>
> In other words, do you think that the problem can be solved by means of
> external library, or one has to act inside the engine (i.e.
> interpreter/compiler) proper?

My proposed approach can work as a library (ok, not on all Prolog
implementation, because you need reflexion on all code and ISO only
depands it for dynamic code). The only downside is some limitation
of the language, e.g. it fails if you try this (which could even be
relaxed if enough is known about <something>.

G =.. <something>
call(G).

Your proposal needs either a generally hookable assert/retract (but in
principal any predicate with side-effects) or goal expansion to rewrite
the calls and some way to ensure that the user doesn't bypass the
expanded goal.

I'm not much in favour of a general hook. You can cache analysis
results, so they need not impose a lot of overhead to the application.

Cheers --- Jan

Paulo Moura

unread,
Feb 2, 2010, 1:52:32 PM2/2/10
to
On Feb 2, 3:18 pm, Jan Wielemaker <j...@hppc323.few.vu.nl> wrote:
> ...

> My proposed approach can work as a library (ok, not on all Prolog
> implementation, because you need reflexion on all code and ISO only
> depands it for dynamic code).

Lack of standardization of Prolog reflection predicates such as
current_predicate/1 and, specially, predicate_property/2 is also
problematic in Logtalk, forcing me to have Prolog-specific hooks to
ensure correct compilation of object predicate clauses. But just to be
clear, your remark above is about using clause/2 (which is also a
reflection predicate) on static predicates?

Cheers,

Paulo

Ulrich Neumerkel

unread,
Feb 2, 2010, 3:04:45 PM2/2/10
to
Paulo Moura <pjlm...@gmail.com> writes:

>On Feb 2, 3:18=A0pm, Jan Wielemaker <j...@hppc323.few.vu.nl> wrote:
>> ...
>> My proposed approach can work as a library (ok, not on all Prolog
>> implementation, because you need reflexion on all code and ISO only
>> depands it for dynamic code).
>
>Lack of standardization of Prolog reflection predicates such as
>current_predicate/1 and, specially, predicate_property/2 ...
> ... But just to be

>clear, your remark above is about using clause/2 (which is also a
>reflection predicate) on static predicates?


I have substantial difficulties following your discussion. Have you all
read 7.5.3? In this subclause, the notion of private and public procedures
are defined.

In particular, it is said that "a static user-defined procedure shall be
private by default"
^^^^^^^^^^

Also, the non-normative Note suggests to add public/1 as an extension.

This is not necessarily the only way to perform the extension.

Mauro DiNuzzo

unread,
Feb 2, 2010, 3:59:36 PM2/2/10
to
The problem is that I want different users to have different privileges on
the same database.

Nothing to do with public/private predicates in the sense of object-oriented
data encapsulation.

I argue that it is not possible to have 100% security with an external
library, unless very very very slow (and possibly, unsafe) execution.

As Jan pointed out, consider the following:

...
Atom = 'expand_file_name',
atom_to_term(Atom, Term, _),
G1 =.. [Term, '*', Files],
call(G1),
( select(File, Files, _), ignore(call(once(delete_file(File)))), fail ;
true),
...

I think it is quite impossible to avoid things like this using term/goal
expansion and clause predicates.


How to solve it?

M

"Ulrich Neumerkel" <ulr...@mips.complang.tuwien.ac.at> wrote in message
news:2010Feb...@mips.complang.tuwien.ac.at...

Paulo Moura

unread,
Feb 2, 2010, 4:10:31 PM2/2/10
to
On Feb 2, 8:04 pm, ulr...@mips.complang.tuwien.ac.at (Ulrich
Neumerkel) wrote:

> Paulo Moura <pjlmo...@gmail.com> writes:
> >On Feb 2, 3:18=A0pm, Jan Wielemaker <j...@hppc323.few.vu.nl> wrote:
> >> ...
> >> My proposed approach can work as a library (ok, not on all Prolog
> >> implementation, because you need reflexion on all code and ISO only
> >> depands it for dynamic code).
>
> >Lack of standardization of Prolog reflection predicates such as
> >current_predicate/1 and, specially, predicate_property/2 ...
> >                                                    ... But just to be
> >clear, your remark above is about using clause/2 (which is also a
> >reflection predicate) on static predicates?
>
> I have substantial difficulties following your discussion.  Have you all
> read 7.5.3?

I have.

> In this subclause, the notion of private and public procedures
> are defined.
>
> In particular, it is said that "a static user-defined procedure shall be
> private by default"
>         ^^^^^^^^^^

But this sentence doesn't contradict Jan: the ISO Prolog standard only
requires that dynamic predicates can be inspected using clause/2. I
don't see nothing in 7.5.3 that requires a complaint Prolog
implementation to offer more than the default "static predicates are
private". But please correct me if I'm wrong.

> Also, the non-normative Note suggests to add public/1 as an extension.

That would be an unfortunate extension to implement given modules,
objects, or any other kind of encapsulation units. This unfortunate
(name) suggestion found its way in the ISO standard for Prolog modules
where (in section 6.8) the predicate properties "public" and "private"
follows from 7.5.3, meaning , precluding their use for representing
predicate scope.

But the point is, as you probably know, most Prolog implementations
don't support using clause/2 over static predicates (assuming that's
what Jan was talking about; I'm waiting his reply).

Cheers,

Paulo

Paulo Moura

unread,
Feb 2, 2010, 4:23:42 PM2/2/10
to
On Feb 2, 8:59 pm, "Mauro DiNuzzo" <pico...@alice.it> wrote:
> The problem is that I want different users to have different privileges on
> the same database.

Why a problem? If you represent each user using a different object,
you have a place to customize the goal-checking code that ensures that
each user specific privileges are respected. The objects representing
the users can inherit the same database. A similar setup might be
possible using modules but I will leave that to others.

> Nothing to do with public/private predicates in the sense of object-oriented
> data encapsulation.

I would say that this would provide you with basic security but thanks
for clarifying what you're after.

> I argue that it is not possible to have 100% security with an external
> library, unless very very very slow (and possibly, unsafe) execution.

Maybe. But I'm not sure that an hypothetic implementation at the
Prolog core level would not hurt the performance of every other
application. I agree with Jan that what the features you want are
better implemented in a library.

Cheers,

Paulo

Jan Wielemaker

unread,
Feb 2, 2010, 5:04:32 PM2/2/10
to

Yes.

--- Jan

Mauro DiNuzzo

unread,
Feb 2, 2010, 5:36:20 PM2/2/10
to

>> The problem is...

>
> Why a problem? If you represent each user using a different object,
> you have a place to customize the goal-checking code that ensures that
> each user specific privileges are respected. The objects representing
> the users can inherit the same database. A similar setup might be
> possible using modules but I will leave that to others.
>


Nice to imagine, but hard to see in practice.
How you can force a user to stay in his/her own "module"... oops "object"?
Do I miss something?
An example would be really appreciated!


>
> Maybe. But I'm not sure that an hypothetic implementation at the
> Prolog core level would not hurt the performance of every other
> application. I agree with Jan that what the features you want are
> better implemented in a library.


Do you think the potential (dis)advantage is the (im)possibility to switch
it off?
In other words, if the issue is just about "performance" you can start your
Prolog system in a sort of "all public" mode, thereby "switching-off" the
goal-checking process.

Anyway, I see your point. But my question is indeed: HOW?
Thanks

M

Ulrich Neumerkel

unread,
Feb 2, 2010, 5:52:28 PM2/2/10
to
Paulo Moura <pjlm...@gmail.com> writes:
>On Feb 2, 8:04=A0pm, ulr...@mips.complang.tuwien.ac.at (Ulrich

>Neumerkel) wrote:
>> Paulo Moura <pjlmo...@gmail.com> writes:
>> I have substantial difficulties following your discussion. Have you all
>> read 7.5.3?
>
>I have.
>
>> In this subclause, the notion of private and public procedures
>> are defined.
>>
>> In particular, it is said that "a static user-defined procedure shall be
>> private by default"
>> ^^^^^^^^^^
>
>But this sentence doesn't contradict Jan: the ISO Prolog standard only
>requires that dynamic predicates can be inspected using clause/2. I
>don't see nothing in 7.5.3 that requires a compliant Prolog

>implementation to offer more than the default "static predicates are
>private". But please correct me if I'm wrong.

You are right. But almost 15 years after 13211-1, we could start
to look for possible extensions. Could we not?

>> Also, the non-normative Note suggests to add public/1 as an extension.
>

>That would be an unfortunate extension ...

Agreed, maybe differently.

Paulo Moura

unread,
Feb 2, 2010, 6:45:44 PM2/2/10
to
On Feb 2, 10:36 pm, "Mauro DiNuzzo" <pico...@alice.it> wrote:
> >> The problem is...
>
> > Why a problem? If you represent each user using a different object,
> > you have a place to customize the goal-checking code that ensures that
> > each user specific privileges are respected. The objects representing
> > the users can inherit the same database. A similar setup might be
> > possible using modules but I will leave that to others.
>
> Nice to imagine, but hard to see in practice.
> How you can force a user to stay in his/her own "module"... oops "object"?
> Do I miss something?

In your original post, you talked about "Prolog and the Web". I assume
that the queries will be sent to the server together with user
identification (but maybe you're thinking about a completely
scenario?). Thus, the queries would be sent to the object identified
by the user credentials. By wrapping a query as an argument to the
message sent to the user object, keeping a user in its own module
would depend on the implementation (method) of that message. This
method would do all the meta-interpreting needed for the calling
semantics and user-specifc privileges.

> An example would be really appreciated!

Sure. I suggest we work on a simple example by private mail and, when
satisfied with the result, post it back to this newsgroup (but I will
be quite busy with stuff-that-justifies-my-salary until the end of
next week).

> > Maybe. But I'm not sure that an hypothetic implementation at the
> > Prolog core level would not hurt the performance of every other
> > application. I agree with Jan that what the features you want are
> > better implemented in a library.
>
> Do you think the potential (dis)advantage is the (im)possibility to switch
> it off?
> In other words, if the issue is just about "performance" you can start your
> Prolog system in a sort of "all public" mode, thereby "switching-off" the
> goal-checking process.

I just think that this is a too special feature to go into the core,
even with an hypothetical switch turned off by default. The possible
issues here go beyond performance. It would be one more thing to
maintain and the ramifications of such features are not clear for me.
How would such a feature interact with other core features? The
apparent orthogonality of Prolog features at the user abstract level
can quickly evaporate when you dive into the implementation.

Cheers,

Paulo


Jan Wielemaker

unread,
Feb 3, 2010, 3:30:19 AM2/3/10
to
On 2010-02-02, Ulrich Neumerkel <ulr...@mips.complang.tuwien.ac.at> wrote:
> Paulo Moura <pjlm...@gmail.com> writes:
>>On Feb 2, 8:04=A0pm, ulr...@mips.complang.tuwien.ac.at (Ulrich
>>Neumerkel) wrote:
>>> Paulo Moura <pjlmo...@gmail.com> writes:
>>> I have substantial difficulties following your discussion. Have you all
>>> read 7.5.3?
>>
>>I have.
>>
>>> In this subclause, the notion of private and public procedures
>>> are defined.
>>>
>>> In particular, it is said that "a static user-defined procedure shall be
>>> private by default"
>>> ^^^^^^^^^^
>>
>>But this sentence doesn't contradict Jan: the ISO Prolog standard only
>>requires that dynamic predicates can be inspected using clause/2. I
>>don't see nothing in 7.5.3 that requires a compliant Prolog
>>implementation to offer more than the default "static predicates are
>>private". But please correct me if I'm wrong.
>
> You are right. But almost 15 years after 13211-1, we could start
> to look for possible extensions. Could we not?

Except the somewhat unfortunate names private and public, I see no
problem with the specification. Demanding an implementation to be able to
show the original program-terms would harm possibilities for optimization
far too much. Just, if you can provide that feature, it is pretty useful
for enhancing the environment and doing all sorts of analysis on the loaded
program rather than the source.

--- Jan

0 new messages