Thread

  1. User-Id Tracking when Portal was started

    Kohei KaiGai <kaigai@kaigai.gr.jp> — 2012-07-02T14:55:39Z

    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>
    
  2. Re: User-Id Tracking when Portal was started

    Robert Haas <robertmhaas@gmail.com> — 2012-07-03T14:58:21Z

    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
    
    
  3. Re: User-Id Tracking when Portal was started

    Kohei KaiGai <kaigai@kaigai.gr.jp> — 2012-07-03T15:33:09Z

    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>
    
    
  4. Re: User-Id Tracking when Portal was started

    Tom Lane <tgl@sss.pgh.pa.us> — 2012-07-03T15:36:42Z

    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
    
    
  5. Re: User-Id Tracking when Portal was started

    Kohei KaiGai <kaigai@kaigai.gr.jp> — 2012-07-03T15:42:17Z

    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>
    
    
  6. Re: User-Id Tracking when Portal was started

    Tom Lane <tgl@sss.pgh.pa.us> — 2012-07-03T16:08:47Z

    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
    
    
  7. Re: User-Id Tracking when Portal was started

    Kohei KaiGai <kaigai@kaigai.gr.jp> — 2012-07-03T16:46:13Z

    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>
    
    
  8. Re: User-Id Tracking when Portal was started

    Robert Haas <robertmhaas@gmail.com> — 2012-07-04T19:44:41Z

    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
    
    
  9. Re: User-Id Tracking when Portal was started

    Kohei KaiGai <kaigai@kaigai.gr.jp> — 2012-07-04T20:24:07Z

    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>
    
    
  10. Re: User-Id Tracking when Portal was started

    Robert Haas <robertmhaas@gmail.com> — 2012-07-05T17:05:30Z

    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