Permissions within a function

Started by Thomas Hallgrenabout 21 years ago17 messages
#1Thomas Hallgren
thhal@mailblocks.com

I'd like some views on the following issue.

The pljava function call handler will resolve a class name using a
loader that in turn uses a specific table in the PostgreSQL database.
Hence, the caller of the function must have select permissions on that
table or the function will fail. I would like to prevent this somehow
but I don't know how to go about that. Is there any way to bypass the
permissions when I do an SPI call from within a call handler somehow?

Regards,
Thomas Hallgren

#2vamsi krishna
vamsi.krishnak@gmail.com
In reply to: Thomas Hallgren (#1)
Re: Permissions within a function

Hi Thomas,

Why dont you create a view on the table and access the view rather
than the table. I guess this would resolve the issue.

What ever select statement you want to have on the table you can make
it a select statement of the view. thus restricting the access to the
main table.

Looking forward to hear from you.

Vamsi Krishna Kundeti

On Fri, 17 Dec 2004 20:12:30 +0100, Thomas Hallgren
<thhal@mailblocks.com> wrote:

Show quoted text

I'd like some views on the following issue.

The pljava function call handler will resolve a class name using a
loader that in turn uses a specific table in the PostgreSQL database.
Hence, the caller of the function must have select permissions on that
table or the function will fail. I would like to prevent this somehow
but I don't know how to go about that. Is there any way to bypass the
permissions when I do an SPI call from within a call handler somehow?

Regards,
Thomas Hallgren

---------------------------(end of broadcast)---------------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to majordomo@postgresql.org so that your
message can get through to the mailing list cleanly

#3Hannu Krosing
hannu@tm.ee
In reply to: Thomas Hallgren (#1)
Re: Permissions within a function

On R, 2004-12-17 at 21:12, Thomas Hallgren wrote:

I'd like some views on the following issue.

The pljava function call handler will resolve a class name using a
loader that in turn uses a specific table in the PostgreSQL database.
Hence, the caller of the function must have select permissions on that
table or the function will fail. I would like to prevent this somehow
but I don't know how to go about that. Is there any way to bypass the
permissions when I do an SPI call from within a call handler somehow?

Would SECURITY DEFINER not work for pljava ?

Or if you are looking for something that has to be done inside the pl
handler maybe you should use another function with SECURITY DEFINER and
owned by superuser for function lookups ?

----------------
Hannu

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Hallgren (#1)
Re: Permissions within a function

Thomas Hallgren <thhal@mailblocks.com> writes:

... Is there any way to bypass the
permissions when I do an SPI call from within a call handler somehow?

No, but you don't have to use SPI. C code can do pretty much what it
wants to.

regards, tom lane

#5Thomas Hallgren
thhal@mailblocks.com
In reply to: vamsi krishna (#2)
Re: Permissions within a function

vamsi,

Why dont you create a view on the table and access the view rather
than the table. I guess this would resolve the issue.

What ever select statement you want to have on the table you can make
it a select statement of the view. thus restricting the access to the
main table.

Looking forward to hear from you.

I don't think a view would help much. I want to completely prevent the
user from viewing or changing any data stored in the table. Using a view
would just move the problem. Now the user must have select access to the
view in order to call the function and that is just as bad.

Regards,
Thomas Hallgren

#6Andrew Dunstan
andrew@dunslane.net
In reply to: Thomas Hallgren (#5)
Re: Permissions within a function

Thomas Hallgren wrote:

vamsi,

Why dont you create a view on the table and access the view rather
than the table. I guess this would resolve the issue.

What ever select statement you want to have on the table you can make
it a select statement of the view. thus restricting the access to the
main table.

Looking forward to hear from you.

I don't think a view would help much. I want to completely prevent the
user from viewing or changing any data stored in the table. Using a
view would just move the problem. Now the user must have select access
to the view in order to call the function and that is just as bad.

Thomas,

I'm not sure if I understand exactly what you want, but would a
"security definer" function help?

cheers

andrew

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Hallgren (#5)
Re: Permissions within a function

Thomas Hallgren <thhal@mailblocks.com> writes:

I don't think a view would help much. I want to completely prevent the
user from viewing or changing any data stored in the table. Using a view
would just move the problem. Now the user must have select access to the
view in order to call the function and that is just as bad.

Just out of curiosity, why use a table at all, if you intend to forbid
all SQL-level access to it? Seems to me that what you want is either
a table (C array) hard-wired in the code, or a configuration file.

regards, tom lane

#8Thomas Hallgren
thhal@mailblocks.com
In reply to: Tom Lane (#7)
Re: Permissions within a function

Tom Lane wrote:

Just out of curiosity, why use a table at all, if you intend to forbid
all SQL-level access to it? Seems to me that what you want is either
a table (C array) hard-wired in the code, or a configuration file.

Andrew Dunstan wrote:

I'm not sure if I understand exactly what you want, but would a
"security definer" function help?

I'll try to give a better explanation of what I'm trying to accomplish.

This is all about access to the java class images, i.e. the actual byte
codes that make out the Java functions that will execute. Class files
are normally grouped into archives called jar files (zip format
essentially) and the SQL 2003 standard for server side Java defines
stored procedures for loading, replacing, and removing such jars. I've
implemented them as functions. A loaded jar is unpacked and stored as
individual class files in a table. The rationale behind this is:

- The file system on the server is a bad place to store things in since
might not be available to the client who loads/unloads jar files.
- A jar file might be fairly big and its not uncommon that only a
fraction of it is brough into memory, if indeed it's used at all.
- The JVM will request classes based on their name. A table lookup is
likely to be faster than scanning a jar or directory on disk. Especially
if the number of classes grow large.

Now, anyone that can execute a PLJava function might cause a class to be
instantiated and since I currently do this with a select through SPI,
all function callers must also have read access to the class table. And
that is not good. In essence, only the administrator should be allowed
to read and execute arbitrary code.

Is there a way to bypass security checks that retains the SQL parser?
I'd like my C-code to do something like:

impersonate pgadmin
SELECT image from class_table
revert to self

If this is not possible, what functions should I learn more about?

Regards,
Thomas Hallgren

#9Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Hallgren (#8)
Re: Permissions within a function

Thomas Hallgren <thhal@mailblocks.com> writes:

This is all about access to the java class images, i.e. the actual byte
codes that make out the Java functions that will execute. Class files
are normally grouped into archives called jar files (zip format
essentially) and the SQL 2003 standard for server side Java defines
stored procedures for loading, replacing, and removing such jars. I've
implemented them as functions. A loaded jar is unpacked and stored as
individual class files in a table.

AFAICS you are choosing to do things in the hardest possible way, on
the basis of completely unfounded suppositions about performance gains.
I recommend the KISS principle. Leave the jar files as jars and let the
Java runtime system manage them.

regards, tom lane

#10Peter Eisentraut
peter_e@gmx.net
In reply to: Thomas Hallgren (#8)
Re: Permissions within a function

Thomas Hallgren wrote:

Is there a way to bypass security checks that retains the SQL parser?
I'd like my C-code to do something like:

impersonate pgadmin
SELECT image from class_table
revert to self

You can use GetUserId() and SetUserId() to flip the current user
identity around as you like. For such a simple query, however, it
might seem better to bypass SPI altogether and do a straight table
lookup through lower-level functions.

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

#11Thomas Hallgren
thhal@mailblocks.com
In reply to: Tom Lane (#9)
Re: Permissions within a function

Tom Lane wrote:

AFAICS you are choosing to do things in the hardest possible way, on
the basis of completely unfounded suppositions about performance gains.
I recommend the KISS principle. Leave the jar files as jars and let the
Java runtime system manage them.

If that was an option, believe me, I would. The current implementation
was not designed and implemented due to my lack of understanding of the
loader mechanisms already present in the runtime. The Java runtime
system just does'nt provide a ClassLoader that can be made to follow the
semantics stipulated by the SQL 2003 Java mapping. That was the major
reason.

I have a well functioning solution. The only lacking part is how to
prevent arbitrary user access to the underlying table. I'd really like
your advice on how to do that.

Regards,
Thomas Hallgren

#12Thomas Hallgren
thhal@mailblocks.com
In reply to: Peter Eisentraut (#10)
Re: Permissions within a function

Peter Eisentraut wrote:

Thomas Hallgren wrote:

Is there a way to bypass security checks that retains the SQL parser?
I'd like my C-code to do something like:

impersonate pgadmin
SELECT image from class_table
revert to self

You can use GetUserId() and SetUserId() to flip the current user
identity around as you like. For such a simple query, however, it
might seem better to bypass SPI altogether and do a straight table
lookup through lower-level functions.

Brilliant! I had no idea it was that simple. SetUserId seems to be
extremely lightweight and just what I need. By using it, I can let my
ClassLoader execute with other restrictions than the function caller
(bypassing SPI is not so good for me since the loader is fairly complex
and will access more than one table).

Thanks for the advice,
Thomas Hallgren

#13Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Hallgren (#1)
Re: Permissions within a function

Thomas Hallgren <thhal@mailblocks.com> writes:

The Java runtime system just does'nt provide a ClassLoader that can be
made to follow the semantics stipulated by the SQL 2003 Java
mapping.

[ raised eyebrow... ] Can the spec really be that broken? They don't
write these things in a total vacuum. Besides, I'd think Sun would get
after them for specifying nonstandard semantics for ClassLoader.

regards, tom lane

#14Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thomas Hallgren (#12)
Re: Permissions within a function

Thomas Hallgren <thhal@mailblocks.com> writes:

Peter Eisentraut wrote:

You can use GetUserId() and SetUserId() to flip the current user
identity around as you like. For such a simple query, however, it
might seem better to bypass SPI altogether and do a straight table
lookup through lower-level functions.

Brilliant! I had no idea it was that simple.

Well, it's not. Exactly what are you going to flip it *to*? You can't
hardwire a particular userid and expect to have a robust solution.

I'd recommend the lower-level approach myself.

regards, tom lane

#15Thomas Hallgren
thhal@mailblocks.com
In reply to: Tom Lane (#13)
Re: Permissions within a function

Tom Lane wrote:

Thomas Hallgren <thhal@mailblocks.com> writes:

The Java runtime system just does'nt provide a ClassLoader that can be
made to follow the semantics stipulated by the SQL 2003 Java
mapping.

[ raised eyebrow... ] Can the spec really be that broken? They don't
write these things in a total vacuum. Besides, I'd think Sun would get
after them for specifying nonstandard semantics for ClassLoader.

You miss the point. There is a standard that ClassLoaders must follow
but that does not mean that the Java runtime comes will all possible
implementations of that standard. My ClassLoader follows both the Java
standard and the SQL spec.

So neither the SQL spec. nor my implementation of it is not broken.

Regards,
Thomas Hallgren

#16Thomas Hallgren
thhal@mailblocks.com
In reply to: Tom Lane (#14)
Re: Permissions within a function

Tom Lane wrote:

Well, it's not. Exactly what are you going to flip it *to*? You can't
hardwire a particular userid and expect to have a robust solution.

I'd recommend the lower-level approach myself.

How about flipping to the owner of the table, (or perhaps schema since
all pljava specific stuff resides in the sqlj schema) that I want to access?

Regards,
Thomas Hallgren

#17Thomas Hallgren
thhal@mailblocks.com
In reply to: Hannu Krosing (#3)
Re: Permissions within a function

Hannu Krosing wrote:

Would SECURITY DEFINER not work for pljava ?

Or if you are looking for something that has to be done inside the pl
handler maybe you should use another function with SECURITY DEFINER and
owned by superuser for function lookups ?

Of course. That's even better then a SetUser. Full control and no magic.
KISS applied the way it should be :-)

Thanks Hannu,
Thomas Hallgren