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.