DOCUMENT #675     
     =======================================================================
     BEYOND PASSWORDS
     =======================================================================
     PRODUCT:  R:BASE                    VERSION :  3.1 or Higher
     =======================================================================
     AREA   :  DATABASE INTEGRITY        CATEGORY:  SECURITY
     =======================================================================
 
 
 
     The R:BASE password system provides control over access to the data
     in your database.  Often you will also want to control access to the
     application or parts of the application.  Even information on
     application menus can be sensitive information that you do not want
     everyone to see.  Or, you may want to control access to data beyond
     the table level, for example, you may only want users to see and edit
     the data that they personally have entered.
 
     Note that if someone is really determined to get in and look at
     information in your database you can't keep them out.  What you can
     do is make it difficult for them.  Also, the following procedures
     assume that you have already set up a system of R:BASE passwords
     restricting access to the database and tables.
 
     
     Control Access to an Application Through Programming
     ====================================================
     --  Don't allow access to R> prompt or main menu
     --  Always exit from the application to DOS
     --  Set escape off
     --  Disable F3 hotkey 
     --  Use startup files
     
     The first step in restricting access to data through an application
     is to make sure that the application does not allow the user access
     to the R> prompt or to the R:BASE main menu.  Only allow users access
     to data through the application where you have control.
 
     Always exit the application to the operating system (DOS) not to
     R:BASE.  When creating an application with Express do not pick the
     action "Exit" from the options menu, this will exit back to R:BASE.
     Instead pick the action "Custom" and enter the command EXIT as the
     custom code.  This will exit the user from R:BASE to the operating
     system when they choose to exit the application.  
 
     Always have "Application break" (ESCAPE) set OFF.  This will prevent
     users from aborting an application by hitting Ctrl-break.  Aborting
     an application will exit users from the application to R:BASE.  By
     making sure "Application break" (ESCAPE) is set OFF, you can keep
     users from accidentally or purposefully aborting an application and
     gaining access to R:BASE outside the application.
 
     Disable the F3 hotkey so that users will not have access to the
     database structure (lists of Tables, Columns, Views, Forms, Reports
     and Variables).  Define a keymap setting the F3 key to
     "[Right][Left]".  When users press F3 it will do nothing and leave
     the cursor in the same position.  Save the keymap to the RBASE.CFG
     file or invoke it through a script file during application startup.
     Note: you can only use this technique to disable the F3 key in 
     R:BASE 4.0.
 
     Use an RBASE.DAT or other startup file to always initialize the
     application when R:BASE is started.  The RBASE.DAT or startup file
     can be encrypted using CodeLock.  Use DOS batch files or an external
     menuing system that will automatically place users in the appropriate
     directories to start R:BASE and the application.
 
     
     Keep Unauthorized Users Out of the Application
     ==============================================
     --  Require a password to connect the database
     --  Require a password to run the application
     --  Create a system_user table to track access to the database
     --  Require a password to access menus in the application
     
     By password protecting all tables and views in a database, you can
     require a valid user password to be entered in order to connect and
     open the database.  This will not prevent the application menus from
     coming up, however.  It just prevents the actions from doing anything
     that requires database access.   The menus display, but they don't do
     anything. 
 
     You can use commands in the RBASE.DAT or startup file to require
     users to enter a password in order to gain access to the application.
     This is not an R:BASE password but one specified in the RBASE.DAT
     file itself.  You can give users three tries to enter the correct
     password, if they don't they are returned to the operating system and
     do not gain access to the application or to R:BASE.  Here's an example
     of code you might use: 
 
 
     USER NONE
     SET ESCAPE OFF  *(makes sure Ctrl-Break will not abort to R>)
     SET VAR vnum INTEGER = 1
     WHILE vnum <= 3 THEN
       CLEAR VAR vpass,vget1,vdots
       SET VAR vnum = (.vnum+1), vget1 TEXT, vpass TEXT, vdots TEXT +
        vpos INTEGER=49
       CLS FROM 10,20 TO 12,61  BLACK
       CLS FROM 9,19 TO 11,60 CYAN
       WRITE 'Please enter your password: ' at 10,22 BLACK ON CYAN
       LABEL getchar
       FILLin vget1=0 USING '' AT 10,.vpos BLACK ON CYAN
       IF vget1 <> '[Enter]' THEN
         SET VAR vdots = (.vdots+'.'), vpass = (.vpass+.vget1), +
          vpos=(.vpos+1)
         WRITE .vdots AT 10,49 BLACK ON CYAN
         GOTO getchar
       ENDIF
       IF vpass = 'pword' THEN
          RUN application IN application.apx
          EXIT
       ELSE
         SET VAR vmsg = (CTR('Invalid Password.  Reenter it.',78)+CHAR(255))
         WRITE .vmsg AT 24,1 GRAY ON RED
         PAUSE 2
         CLS FROM 24 TO 25
         CLS FROM 10,48 TO 10,60 CYAN
       ENDIF
     ENDWHILE
     SET VAR vmsg = (CTR('No valid password entered.  You cannot access +
      system.', 78) + CHAR(255) )
     WRITE .vmsg AT 24,1 GRAY ON RED
     PAUSE 2
     CLS
     EXIT
     
     Be sure to encrypt the R:BASE.DAT or startup file with CodeLock so
     that the passwords you're checking are not readable by viewing the
     file.
     
     You can enhance this by using R:BASE tables to store the passwords. 
     You assign each person a personal password.  The personal password is
     stored in an R:BASE table along with the matching R:BASE system
     password.  This allows you to restrict the number of different R:BASE
     passwords you need to assign, but each person can have their own
     password.  In addition, you can have a user log table which will keep
     track of who is using the system, and who has tried to gain access to
     the system.  Here's an example.  
 
     Create two tables:
     
     SECRET table:  USERNAME
                    PWORD  personal password
                    SYSPW  system (R:BASE) password
 
     USERLOG table: SYSPW  password entered
                    USERNAME
                    TIME_IN
                    DATE_IN
                    TIME_OUT
                    DATE_OUT
                    PCHECK  invalid/valid password entered
 
     The command file requires users to enter their name and then their
     personal password.  It checks the SECRET table for the combination of
     name and password and gives 3 chances for the user the enter the
     correct password for their name.  Each try is logged into the USERLOG
     table.  R:BASE table passwords (read/modify) are assigned to the two
     tables.  Again the program code must be encrypted so that the
     passwords that are necessary for the program to execute are not
     readable.  
 
     When the correct password combination is entered, the user starts the
     application.  If correct combination is not entered, the user is
     exited to the DOS prompt.
     
     SET MESSAGES OFF
     SET ERROR MESSAGES OFF
     USER NONE
     SET ESCAPE OFF
     SET ERROR VAR verr
     SET VAR vnum INTEGER = 1
     CLS FROM 10,20 TO 12,61  BLACK
     CLS FROM 9,19 TO 11,60 CYAN
     WRITE 'Enter your name:  ' at 10,22 BLACK ON CYAN
     FILLIN vusername=20 USING '' AT 10,39 BLACK ON CYAN
     IF vusername IS NULL THEN
       SET VAR vmsg = BREAK
     ENDIF
     CLS FROM 9,19 TO 11,60 CYAN
     WHILE vnum <= 3 THEN
       CLEAR VAR vpass,vget1,vdots
       SET VAR vnum = (.vnum+1), vget1 TEXT, vpass TEXT, vdots TEXT +
             vpos INTEGER=49
       CLS FROM 10,20 TO 12,61  BLACK
       CLS FROM 9,19 TO 11,60 CYAN
       WRITE 'Please enter your password: ' AT 10,22 BLACK ON CYAN
       LABEL getchar
       FILLin vget1=0 USING '' AT 10,.vpos BLACK ON CYAN
       IF vget1 <> '[Enter]' THEN
         SET VAR vdots = (.vdots+'.'), vpass = (.vpass+.vget1), vpos=(.vpos+1)
         WRITE .vdots AT 10,49 BLACK ON CYAN
         GOTO getchar
       ENDIF
       SET USER junk *(the read password for the SECRET table)
       CONN concomp
       SET VAR vpw = syspw IN secret WHERE pword=.vpass AND +
        username=.vusername
       SET V vhold=.verr
       SET USER none
       IF vhold = 0 THEN
         SET USER junk  *(the modify password for the USERLOG table)
         INSERT INTO userlog (syspw,username,time_in,date_in,pcheck) +
            VALUES (.vpass,.vusername,.#time,.#date,'VALID')
         CLS
         SET USER .vpw
         RUN application IN application.apx
         SET USER junk  *(the modify password for the USERLOG table)
         UPDATE userlog SET time_out=.#time, date_out=.#date WHERE +
            syspw = .vpass AND username = .vusername AND date_in=.#date
     EXIT
       ELSE
         SET USER junk   *(the modify password for the USERLOG table)
         INSERT INTO userlog (syspw,username,time_in,date_in,pcheck) +
            VALUES (.vpass,.vusername,.#time,.#date,'INVALID')
         SET USER NONE
         DISC
         SET VAR vmsg = (CTR('Invalid Password.  Reenter it.',78)+CHAR(255))
         WRITE .vmsg AT 24,1 GRAY ON RED
         PAUSE 2
         CLS FROM 24 TO 25
         CLS FROM 10,48 TO 10,60 CYAN
       ENDIF
     ENDWHILE
     SET VAR vmsg = (CTR('No valid password entered.  You cannot access +
      system.', 78) + CHAR(255) )
     WRITE .vmsg AT 24,1 GRAY ON RED
     PAUSE 2
     CLS
     EXIT
     
 
     You can also control access to menu levels in an application.  Use
     one of the following two techniques, depending on whether you want to
     continue modifying the application with Express. 
     
     
     Option 1:  Express modifiable
     =============================
     First create an ASCII file that has one command in it: RUN
     application IN application.APX.  This file must remain as an ASCII
     file.  Modify the application, choose to "Insert an action" before
     the menu to be restricted.   Choose Custom or Macro for the action
     and insert password checking code similar to that in the examples
     above.  If users don't enter the correct password use the QUIT TO
     command instead of EXIT; QUIT TO the ASCII file that restarts the
     application.  This will always take users to the main menu of the
     application, even if they are at a third level menu.  
     
     When done, you have 2 actions defined for the particular menu
     selection that goes to the lower level menu; the first action does
     password checking, the second action displays the menu if the
     correct password is entered.
 
 
     Option 2:  Not "Expressable"
     ============================     
     If continuing to modify the application with Express is not an issue,
     use this method.  Modify the application and follow the same
     procedure for inserting an action, and choose Custom or Macro for the
     action.  But instead of using QUIT TO ASCII_file when the password is
     incorrect, use either SET VAR LEVEL2 = 0 or SET VAR LEVEL3 = 0.  Use
     LEVEL2 if you checking a second level menu, LEVEL3 if it is a third
     level menu.  Application Express inserts a RUN command for the
     custom/macro code immediately prior to a SET VAR command that
     controls the next menu level.  The lines of code in the .APP file 
     look like this:
 
          CASE 'Print reports'
            RUN pcheck IN application.apx
            SET VAR LEVEL3 INT = 1
            WHILE LEVEL3 = 1 THEN
 
     Simply switch the two lines of code, "RUN... " and "SET VAR
     LEVEL3...", so the code looks like this instead:
 
          CASE 'Print reports'
            SET VAR LEVEL3 INT = 1
            RUN pcheck IN application.apx
            WHILE LEVEL3 = 1 THEN
 
     Then, if the correct password is not entered, the WHILE condition
     fails (variable LEVEL3 =0), the menu is not displayed and the user
     returns to the previous menu (either the main menu of the application
     of application or the second level menu).  Because you are editing the
     .APP file you need to CodeLock the file to create a new .APX file to run. 
 
     This application is no longer be modifiable in Application Express, 
     Express won't know about the custom editing you have done to the .APP 
     file.
     
 
     Control Data Access Using Forms
     ===============================
     --  Locate only specific fields
     --  Use form passwords
     --  Use Form, table and field settings to restrict editing
          --  Disable Shift-F3 pop-ups
     --  Read-only forms
 
     R:BASE forms provide application developers with any number of
     techniques for limiting/restricting access to data.  First and
     foremost is the fact that you, the application developer, limit the
     data that is located or displayed on the form.  You choose which
     columns the user can view and modify by placing or not placing those
     fields on the form.  By restricting user access to data through forms
     you immediately limit the data they can view or edit.  There is no
     direct access to other columns in the underlying table or view
     through the form.  
 
     In addition, forms has form, table and field level control on editing
     data, its own password system (see article "Passwords - a Primer" in
     this issue of the Exchange) and, in 4.0, you can use views.  
 
     At the form level (Form settings) a developer specifies that the form
     can be used to add new rows or to edit existing rows.  The form menu
     can be customized or removed altogether.  At the table level, Table
     settings are used to specify whether users can add new rows, edit
     existing rows or delete rows from the table.  At the field level,
     individual fields in tables can be made non-editable through the
     Field settings screen.  
 
     To make sure that users only have access to the data you want them to
     see, disable the Shift-F3 key for default pop-ups in forms (redefine
     the key, see disabling the F3 key above), or define a specific pop-up
     for each field in a form.  By default, Shift-F3 will pop-up a menu
     and display all the current data values in the table for the
     particular column.  Instead of using Shift-F3, use an Entry/exit
     procedure and key pop-ups off of the F2 key.  This procedure is
     described in the May/June 1992 Exchange in "A Collection of
     Entry/Exit Procedures", Conditional multi-column pop-up menu 
     (document #645 on our automated FAX server, 206-649-2789).
 
     There are many application situations where it's necessary for people
     to see data, but not be able to edit it.  R:BASE provides a number of
     ways to create read-only forms.
 
     1. Use form passwords to create a read-only form by setting a modify
     password on the form.  If the current user is not the same as the
     modify password, the form displays and data appears but the "No
     editable data" message displays on line 24.
 
     2. Use Table settings/field settings combinations to create a
     read-only form.  An individual table on a multi-table form can be
     specified as read-only by changing Table settings to NO for "Add new
     rows" and "Change data", but you need to be careful when doing this. 
     If any table on a multi-table form is set to say NO to "Add new rows"
     then the form cannot be used to add data.  The only exception is if
     the table has a same-table lookup defined for it.  If the table
     settings say NO to "Change data" then users can page up and page down
     through the data but they see the message "No editable data" on line
     24.  The cursor does not land in any fields on the form and you cannot
     scroll through NOTE or TEXT fields.  
 
     To scroll through NOTE or TEXT fields, define an expression to lookup
     the note or text data into a variable, locate the variable on the
     form and make the field settings editable.  Because it is a variable,
     it won't matter if users inadvertently change data, it won't be saved
     to the table.  
          
     If you don't want your users to see the "No editable data message",
     locate a dummy variable for each table on the form.  Use Field
     settings to make all fields but the dummy variable non-editable.  The
     dummy variable gives the cursor a place to land. 
 
     3. Do not GRANT UPDATE permission to the tables the form is based on. 
     Users without UPDATE permission are able to view the data but
     cannot change it.  They see the message "No editable data" and
     the cursor does not land in any fields on the form.
 
     4. With R:BASE 4.0, you can use a view to create a read-only form.  A
     multi-table view is by definition non-editable.  When using a
     single-table view, GRANT SELECT permission on the view only.