14 Sept. 2002
                     SREhttp/2 and Dynamic Privileges

I.      Introduction
I.a:       A Security Note
II.     The DYNPRIV.CMD addon
II.a       The DYNP_LOG.CMD addon
II.a.1.       Syntax
II.a.2.       What is stored
III.    The SREH2_DYNAMIC_PRIVS procedure
III.a.     Details on SREH2_DYNAMIC_PRIVS
IV.     The DYNPRIV.REX SSI procedure to read & set dynamic privileges
IV.a.      Syntax   
IV.b.      Example  

                        ------------------

I. Introduction

Dynamic privileges are user specific information granted for a short
duration.  Typically, they are extra "client privileges" required 
for short-term access to special resources. However, they don't have
to be privileges -- they can be any text-strings containing client-specific 
data that is usefully stored for a short timespan.

There are two steps in the use of dynamic privileges:
   1) Assigning dynamic privileges to a user.
   2) Looking up dynamic privileges.

   Step 1 is handled by a number of different mechanisms, including
   the DYNP_LOG.CMd and the DYNPRIV.REX "SSI" and "EXEC" procedure -- 
   see section II and IV.

   Step 2 is handled by the SREH2_DYNAMIC_PRIVS procedure -- see section III.

                        ------------------

I.a  ** A Security Note  ***

     Dynamic privileges are NOT DESIGNED TO BE HIGHLY SECURE.
     While they do not offer any obvious exploitable flaws, our 
     implementation does not use encrypted transmission mechanisms, 
     or other security enhancing features.

     Therefore:
        we do NOT recommend use of "dynamic privileges" for controlling 
        access to critical resources.

                        ------------------

II. Assigning dynamic privileges to a user

SREhttp/2 supports a number of mechanisms for assigning dynamic privileges
to a client
   a) The DYNP_LOG.CMD addon. This is an "augmented-logon" procedure -- 
      the client is presented with an authorization screen and asked 
      to provide a new username. However, this new username will be assigned,
      as  "dynamic" privileges, the client privileges of his current username 
      (of the username before DYNP_LOG was invoked).

      DYNP_LOG is fairly easy to use (requiring a fairly easy to specify link).
      It's also fairly secure, as it relies on SREhttp/2's authorization
      mechanism, and passes little information to the client.

   b) The DYNPRIV.REX "interpretable file" and "EXEC procedure". 
      This is used to grant dynamic privileges to the client, and to check
      if a client has been granted server side includes.


II.a  The DYNP_LOG.CMD addon

DYNPRIV.CMD  is designed to work with most browser's normal authorization
mechanism.  The following steps describe how DYNP_LOG.CMD works:

   1) You place a "do you want to (re) logon?" link (or add a HIDDEN element to
      an HTML form), on a web page.  This link (or form) contains information about
      what resource should be requested after a successful (re) logon (see
      the II.a.1 for the syntax).

   2) Upon clicking on this link, the client's current username and password are
      used to find his current privileges (as stored in the possibly host-
      specific USERS.CFG file).

   3) The
        a) current username and privileges, 
        b) any "dynamic privileges" currently assigned to this username, 
        c) and other information  
      are stored in a  temporary location on the server. 

      Note:
         If there is no username available, or there are no privileges 
         associated with this username, placeholder username & privileges 
         are used.

   4) The client is then redirected to  /DYNP_LOG.CMD?xxx, where "xxx" is
      a set of customized instructions.
      Upon being invoked, DYNP_LOG.CMD  will extract a username included in an 
      Authorization: request header.

   5) DYNP_LOG.CMD lookups the old username & privilege information (stored
      in step 3, retrived by using information in the "xxx" of step 4).
      If the new username is the same, send an authorization request
      and repeat step 5.

      In other words -- DYNP_LOG.CMD  INSISTS on either a first-time
      logon, or a "re-logon" if the prior username wasn't good enough!

   6) The stored  username & privileges, and the current username & privileges,
      are stored as "dynamic privileges". They are stored using the current 
      username as an identifier. As discussed in section III, SREH2_DYNAMIC_PRIVS
      can then easily lookup these "dynamic privileges".

   7) Note that this is a cascading storage -- one can re-logon several
      times, with prior "dynamic privileges" retained.
      However, this is also "dynamic" -- after a sufficiently long
      timespan of inactivity, these dynamic privileges are discarded 
      (by default, after 15 minutes).


II.a.1. Syntax:
  
DYNP_LOG.CMD can be invoked using a static link, or via a form:
For purposes of documentation, let's assume a static link is used.

Syntax:
    <a href="/dynp_log.cmd?/cool_addon.cmd?mode=1&toad=3">Please re-logon</a>

Note that the "options" portion of the selector (what follows
the first question mark) is the URL that will eventually returned
to the client, after successful re-logon. As indicated in the above
example, this can be any legal URL; it can contain ?s, &s, etc. (but
spaces must be URL-encoded).

Although is it highly recommended that this URL containing "option" 
be included, it is not strictly necessary.  If it is not:
  1) DYNP_LOG will look for a Referer: request header, and use its
     value
  2) If no Referer: request header is available, a generic final-response
     is used.


II.a.2. What is stored

After a successful DYNP_LOG invocation, an entry in the dynamic-privileges 
database will be created, one that can be easily read by the SREH2_DYNAMIC_PRIVS
procedure. This will be identified by the current username, and will have
its value...
   1) If an older username(s) was given, the  dynamic-privileges associated with it
      (if any exist), and
   2) a space delimited list, starting with the current username, and followed
      by the list of dynamic privileges.

For example, after several "re-logons", ending with the FRED username, the value
of FRED "user" entry in the dynamic-privileges database might look like:

        BOB dogs cats ;  JILL planes subs  ; FRED barney wilma 

Note:

    *  each set of "username and privileges" is seperated by a " ; ", 
    *  each set starts with the "username".
    *  the username is case insenstive 
    
    * To read this (say, from an addon), you could use:
        new_privs=sreh2_dynamic_privs('READ','!USER',,,id_info)
  
        The !USER means "extract the current username, and find dynamic 
        privileges stored under this current username".
        In this case, given that you know the current username is FRED, you 
        could also use:
             new_privs=sreh2_dynamic_privs('READ','!USER:FRED',,,id_info)

    * Secret privileges, if they are specified, they are seperate by a comma.
      For example:
        BOB dogs cats ;  JILL2 planes  subs , encrypt:ufos ; FRED barney wilma      

    * Duration: a username's dynamic-privileges are stored for 15 minutes, You can 
      change this, on  a selector specific basis, by using the DYNPRIV_DURATION 
      "option" (which you can set in your possibly host-specific ATTRIBS.CFG file).

                                ------------------


                        ------------------

III. The SREH2_DYNAMIC_PRIVS procedure

The SREH2_DYNAMIC_PRIVS REXX procedure is used to set and read 
"dynamic privileges". SREH2_DYNAMIC_PRIVS is optimized to work with the
DYNPRIV addon (more precisely, DYNPRIV is optimized to work with
SREH2_DYNAMIC_PRIVS)

Syntax:
  stuff=sreh2_dynamic_privs(action,aname,avalue,lifespan,id_info)

where:

    action: one of LIST, DELETE, WRITE, AUGMENT, READ, or RESET

    aname: a case-insensitive username, or other identifier, identifiying
           the record where the dynamic privileges are stored.
           As discussed below, several special values can also be used:
           !IP, !USER, and !COOKIE.

    avalue:  the dynamic privilegs to store. Used only by the WRITE and
             AUGMENT actions.

    lifespan: the lifespan, in minutes, of this record. If not specified,
              a default of 15 minutes is used.

    id_info: Optional, the ID_INFO


Note:
   SREH2_DYNAMIC_PRIVS uses the SRE_CACHE SRE2003 procedure.

                        ------------------

III.a. Details on SREH2_DYNAMIC_PRIVS

The supported  actions:

 LIST - list info on current number of records (containing dynamic privileges)
        The returned value has the format:
           #entries_in_cache (crlf)
           identifier','#reads','list_of_dynamic_privs (crlf)
                ...

 DELETE - remove the "aname" record from dynpriv

 WRITE   - add the "aname" record in dynpriv

 AUGMENT - add new data to the "aname" record
           If "aname" does not currently exist, AUGMENT is the same as WRITE.
           When adding data (when the "aname" record exists and has
           data in it), AUGMENT will append a ' ; ' to the old data,
           and then append the new data (the "avalue" argument).


 READ   - read the data stored in the "aname" record
 RESET  - remove all "dynamic privilege" records


Special names
  There are several reserved values of "aname", all of which start with a !
  Any other name that starts with a ! is disallowed.

    !IP          - lookup the client's numeric IP address, and use it
                   as the identifier
    !USER        - lookup the username (as supplied in  an Authentication 
                   header), and use it. If no username is available (say,
                   because an Authentication request header was not sent),
                   return ' '
    !COOKIE      - lookup the name in the DYNPRIV cookie, and use it
    !COOKIE=xxx  - similar to !COOKIE, but use the "XXX" cookie instead of DYNPRIV
                   For !COOKIE and !COOKIE=xxx, if the cookie does not exist,
                   return ' '

    !IP:xxx, !USER:xxx,
     and !COOKIE:xx -- use this as a name. That is !USER:FOOBAR will
                       be used as the name, including the !USER: portion.
                       This is used to explicitily read, and write, records that
                       can be read by the !IP, !COOKIE, and !USER names.

                        ------------------

IV.  The DYNPRIV.REX SSI procedure to read & set dynamic privileges


DYNPRIV.REX is an "INTERPRETable server side include" procedure.
It uses a cookie based mechanism to award, and to lookup, dynamic
procedures assigned to this client. One could use DYNPRIV.REX to
force sequential access to documents -- by granting a
dynamic privilege in "document 1" that is need by "document 2".

DYNPRIV.REX can also be used as an "EXEC" procedure. Used as
an EXEC, DYNPRIV.REX can be used to deny access to a set of
files (say, image files) to clients who have not first visited
an introductory page.


IV.a. Syntax:

In either use (as an INTERPRETable SSI or an EXEC procedure), the 
syntax is similar:

As an INTERPRETable SSI (included in an SSI html file)
    <!-- INTERPRET FILE DYNPRIV.REX  action , privileges -->

As an EXEC procedure (as included in an ATTRIBS.CFG file):

option: EXEC DYNPRIV.REX action, privileges

where:
  action: Either
             ADD   [duration]
             CHECK [failure_selector]

  privileges: a space delimited list of dynamic privileges

Details on action  (note that action is case insensitive):
     ADD:  ADD is used to assign dynamic privileges to a client.
           This uses a cookie based mechanism where:
                1) an randomly named identifier is generated
                2) the privileges are stored (in the DYNAMIC_PRIVILEGES
                   database) under this identifier
                3) a Set-Cookie: header is sent to the client, that
                   points to this identifier
            [DURATION] is optional. If included, it is the number of
            minutes these dynamic privileges will be retained. If not
            included, the default of 15 minutes is used.
                
            Note that ADDs within a single SSI file are cumulative.
            Also, if an SSI document is re-requested, and dynamic privileges
            ADDed within this document have not exceeded their life span, the 
            clock will be restarted.


   CHECK:   Check to see if any of the privileges have been assigned to
            the client. Note that if you list multiple privileges in a CHECK,
            only one of them needs to be available. If you want to require the   
            existence of multiple privileges, you can use multiple
                   <!-- INTERPRET FILE DYNPRIV.REX Check ... --> 
            elements in the document.
        
           [failure_selector] is optional. This is only used if the client does
           not have the required dynamic privileges -- in which case, a 302 
           (temporary) redirection response is used to send the client to
           the failure_selector. The failure_selector should be any absolute,
           or relative, URI -- it's treated subject to the usual SREhttp/2
           access controls, etc.

           If a failure_selector is not specified, then a generic response is
           sent if the client does not have sufficient dynamic privileges.

Examples:

   ADD     , DOG CAT
   CHECK /hello/readme1.shtml , LION
   Add   30 , Tigers

   

IV.b. Example  

Assume a T1.HTM file which includes the statement:
    <!-- INTERPRET FILE DYNPRIV.REX  ADD 20 , P1  -->
and a T2.HTM file with
    <!-- INTERPRET FILE DYNPRIV.REX CHECK TEST/F1.HTM , P1 P2 , 20 -->

A request for T1.HTM will cause a P1 "dynamic privilege" to be added to the
client's dynamic privilege list (for the next 10 minutes).  Within this time
period, a request for T2.HTM will be honored. After this time period,
a request for T2.HTM will result in a redirect to T1.HTM -- after which
T2.HTM will become available (for another 10 minutes).


