Обсуждение: User-Id Tracking when Portal was started

Поиск
Список
Период
Сортировка

User-Id Tracking when Portal was started

От
Kohei KaiGai
Дата:
The attached patch is delivered from the discussion around row-level
access control feature. A problem Florian pointed out is refcursor
declared in security definer function. Even though all the permission
checks are applied based on privilege of the owner of security-definer
function in case when it tries to define a cursor bound to a particular
query, it shall be executed under the credential of executor.
In the result, "current_user" or "has_table_privilege()" will return
unexpected result, even if it would be used in as a part of security
policy for each row.

This patch enables to switch user-id when user tried to execute
a portal being started under the different user's credential.

postgres=# CREATE FUNCTION f1(refcursor) RETURNS refcursor
postgres-#     SECURITY DEFINER LANGUAGE plpgsql
postgres-#     AS 'BEGIN OPEN $1 FOR SELECT current_user,* FROM t1;
postgres'#         RETURN $1; END';
CREATE FUNCTION

postgres=# SET SESSION AUTHORIZATION alice;
SET
postgres=> BEGIN;
BEGIN
postgres=> SELECT f1('abc');
 f1
-----
 abc
(1 row)

postgres=> FETCH abc;
 current_user | a |  b
--------------+---+-----
 kaigai       | 1 | aaa          <=== 'abc' was started under the
kaigai's privilege
(1 row)

postgres=> SELECT current_user;
 current_user
--------------
 alice
(1 row)

postgres=> DECLARE xyz CURSOR FOR SELECT current_user, * FROM t1;
DECLARE CURSOR
postgres=> FETCH xyz;
 current_user | a |  b
--------------+---+-----
 alice        | 1 | aaa
(1 row)

postgres=> RESET SESSION AUTHORIZATION;
RESET
postgres=# FETCH xyz;          <=== 'xyz' was started under the
kaigai's privilege
 current_user | a |  b
--------------+---+-----
 alice        | 2 | bbb
(1 row)


BTW, same problem will be caused in case when security label of
the client would be switched. Probably, a hook should be injected
around the places where I patched with this patch.

Thanks,
--
KaiGai Kohei <kaigai@kaigai.gr.jp>

Вложения

Re: User-Id Tracking when Portal was started

От
Robert Haas
Дата:
On Mon, Jul 2, 2012 at 10:55 AM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
> The attached patch is delivered from the discussion around row-level
> access control feature. A problem Florian pointed out is refcursor
> declared in security definer function. Even though all the permission
> checks are applied based on privilege of the owner of security-definer
> function in case when it tries to define a cursor bound to a particular
> query, it shall be executed under the credential of executor.
> In the result, "current_user" or "has_table_privilege()" will return
> unexpected result, even if it would be used in as a part of security
> policy for each row.

Why not just save and restore the user ID and security context
unconditionally, instead of doing this kind of dance?

+               if (portal->userId != GetUserId())
+                       SetUserIdAndSecContext(portal->userId, portal->secCo
+               else
+                       saveUserId = InvalidOid;

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: User-Id Tracking when Portal was started

От
Kohei KaiGai
Дата:
2012/7/3 Robert Haas <robertmhaas@gmail.com>:
> On Mon, Jul 2, 2012 at 10:55 AM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>> The attached patch is delivered from the discussion around row-level
>> access control feature. A problem Florian pointed out is refcursor
>> declared in security definer function. Even though all the permission
>> checks are applied based on privilege of the owner of security-definer
>> function in case when it tries to define a cursor bound to a particular
>> query, it shall be executed under the credential of executor.
>> In the result, "current_user" or "has_table_privilege()" will return
>> unexpected result, even if it would be used in as a part of security
>> policy for each row.
>
> Why not just save and restore the user ID and security context
> unconditionally, instead of doing this kind of dance?
>
> +               if (portal->userId != GetUserId())
> +                       SetUserIdAndSecContext(portal->userId, portal->secCo
> +               else
> +                       saveUserId = InvalidOid;
>
In case when CurrentUserId was updated during the code block
(E.g, execution of SET SESSION AUTHORIZATION), it overwrites
this update on restoring user-id and security-context.

Comparison of user-id is a simple marker to check whether this
portal contain an operation to switch user-id, because these
operations are prohibited within security restricted context.
(Is there some other good criteria?)

Thanks,
-- 
KaiGai Kohei <kaigai@kaigai.gr.jp>


Re: User-Id Tracking when Portal was started

От
Tom Lane
Дата:
Kohei KaiGai <kaigai@kaigai.gr.jp> writes:
> 2012/7/3 Robert Haas <robertmhaas@gmail.com>:
>> Why not just save and restore the user ID and security context
>> unconditionally, instead of doing this kind of dance?
>> 
>> +               if (portal->userId != GetUserId())
>> +                       SetUserIdAndSecContext(portal->userId, portal->secCo
>> +               else
>> +                       saveUserId = InvalidOid;
>> 
> In case when CurrentUserId was updated during the code block
> (E.g, execution of SET SESSION AUTHORIZATION), it overwrites
> this update on restoring user-id and security-context.

Um... what should happen if there was a SET SESSION AUTHORIZATION
to the portal's userId?  This test will think nothing happened.
        regards, tom lane


Re: User-Id Tracking when Portal was started

От
Kohei KaiGai
Дата:
2012/7/3 Tom Lane <tgl@sss.pgh.pa.us>:
> Kohei KaiGai <kaigai@kaigai.gr.jp> writes:
>> 2012/7/3 Robert Haas <robertmhaas@gmail.com>:
>>> Why not just save and restore the user ID and security context
>>> unconditionally, instead of doing this kind of dance?
>>>
>>> +               if (portal->userId != GetUserId())
>>> +                       SetUserIdAndSecContext(portal->userId, portal->secCo
>>> +               else
>>> +                       saveUserId = InvalidOid;
>>>
>> In case when CurrentUserId was updated during the code block
>> (E.g, execution of SET SESSION AUTHORIZATION), it overwrites
>> this update on restoring user-id and security-context.
>
> Um... what should happen if there was a SET SESSION AUTHORIZATION
> to the portal's userId?  This test will think nothing happened.
>
In my test, all the jobs by SET SESSION AUTHORIZATION was cleaned-up...
It makes nothing happen from viewpoint of users.

Thanks,
-- 
KaiGai Kohei <kaigai@kaigai.gr.jp>


Re: User-Id Tracking when Portal was started

От
Tom Lane
Дата:
Kohei KaiGai <kaigai@kaigai.gr.jp> writes:
> 2012/7/3 Tom Lane <tgl@sss.pgh.pa.us>:
>> Um... what should happen if there was a SET SESSION AUTHORIZATION
>> to the portal's userId?  This test will think nothing happened.

> In my test, all the jobs by SET SESSION AUTHORIZATION was cleaned-up...
> It makes nothing happen from viewpoint of users.

My point is that it seems like a bug that the secContext gets restored
in one case and not the other, depending on which user ID was specified
in SET SESSION AUTHORIZATION.
        regards, tom lane


Re: User-Id Tracking when Portal was started

От
Kohei KaiGai
Дата:
2012/7/3 Tom Lane <tgl@sss.pgh.pa.us>:
> Kohei KaiGai <kaigai@kaigai.gr.jp> writes:
>> 2012/7/3 Tom Lane <tgl@sss.pgh.pa.us>:
>>> Um... what should happen if there was a SET SESSION AUTHORIZATION
>>> to the portal's userId?  This test will think nothing happened.
>
>> In my test, all the jobs by SET SESSION AUTHORIZATION was cleaned-up...
>> It makes nothing happen from viewpoint of users.
>
> My point is that it seems like a bug that the secContext gets restored
> in one case and not the other, depending on which user ID was specified
> in SET SESSION AUTHORIZATION.
>
Sorry, the above description mention about a case when it does not use
the marker to distinguish a case to switch user-id from a case not to switch.
(I though I was asked the behavior if this logic always switches /
restores ids.)

The patch itself works correctly, no regression test failed even though
several tests switches user-id using SET SESSION AUTHORIZATION.

Thanks,
-- 
KaiGai Kohei <kaigai@kaigai.gr.jp>


Re: User-Id Tracking when Portal was started

От
Robert Haas
Дата:
On Tue, Jul 3, 2012 at 12:46 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>> My point is that it seems like a bug that the secContext gets restored
>> in one case and not the other, depending on which user ID was specified
>> in SET SESSION AUTHORIZATION.
>>
> Sorry, the above description mention about a case when it does not use
> the marker to distinguish a case to switch user-id from a case not to switch.
> (I though I was asked the behavior if this logic always switches /
> restores ids.)
>
> The patch itself works correctly, no regression test failed even though
> several tests switches user-id using SET SESSION AUTHORIZATION.

I don't believe that proves anything.  There are lots of things that
aren't tested by the regression tests, and there's no guarantee that
any you've added cover all bases, either.  We always treat user-ID and
security context as a unit; you haven't given any reason why this case
should be handled differently, and I bet it shouldn't.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company


Re: User-Id Tracking when Portal was started

От
Kohei KaiGai
Дата:
2012/7/4 Robert Haas <robertmhaas@gmail.com>:
> On Tue, Jul 3, 2012 at 12:46 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>>> My point is that it seems like a bug that the secContext gets restored
>>> in one case and not the other, depending on which user ID was specified
>>> in SET SESSION AUTHORIZATION.
>>>
>> Sorry, the above description mention about a case when it does not use
>> the marker to distinguish a case to switch user-id from a case not to switch.
>> (I though I was asked the behavior if this logic always switches /
>> restores ids.)
>>
>> The patch itself works correctly, no regression test failed even though
>> several tests switches user-id using SET SESSION AUTHORIZATION.
>
> I don't believe that proves anything.  There are lots of things that
> aren't tested by the regression tests, and there's no guarantee that
> any you've added cover all bases, either.  We always treat user-ID and
> security context as a unit; you haven't given any reason why this case
> should be handled differently, and I bet it shouldn't.
>
This patch always handles user-id and security context as a unit.
In case when it was switched, then it shall be always restored.
And, in case when it was not switched, then it shall never be restored.

Was my explanation confusing?
-- 
KaiGai Kohei <kaigai@kaigai.gr.jp>


Re: User-Id Tracking when Portal was started

От
Robert Haas
Дата:
On Wed, Jul 4, 2012 at 4:24 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
> 2012/7/4 Robert Haas <robertmhaas@gmail.com>:
>> On Tue, Jul 3, 2012 at 12:46 PM, Kohei KaiGai <kaigai@kaigai.gr.jp> wrote:
>>>> My point is that it seems like a bug that the secContext gets restored
>>>> in one case and not the other, depending on which user ID was specified
>>>> in SET SESSION AUTHORIZATION.
>>>>
>>> Sorry, the above description mention about a case when it does not use
>>> the marker to distinguish a case to switch user-id from a case not to switch.
>>> (I though I was asked the behavior if this logic always switches /
>>> restores ids.)
>>>
>>> The patch itself works correctly, no regression test failed even though
>>> several tests switches user-id using SET SESSION AUTHORIZATION.
>>
>> I don't believe that proves anything.  There are lots of things that
>> aren't tested by the regression tests, and there's no guarantee that
>> any you've added cover all bases, either.  We always treat user-ID and
>> security context as a unit; you haven't given any reason why this case
>> should be handled differently, and I bet it shouldn't.
>>
> This patch always handles user-id and security context as a unit.
> In case when it was switched, then it shall be always restored.
> And, in case when it was not switched, then it shall never be restored.
>
> Was my explanation confusing?

It's not that your explanation is confusing; it's that it doesn't
match the code.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company