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: Please re-logon 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) 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 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: and a T2.HTM file with 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).