File Access Privileges

Historically, the typical AMOS approach to limiting access to sensitive application programs was to group them within a password-protected menu program. This works reasonably well in simple cases, but obviously breaks down as the complexity of the application or of its security needs increases. For example, if several people need access to the protected programs, then they all need to share a password. If one of those users leaves the company, then you probably need to change the password, which can be a pain if many other users are involved. The problem gets worse when you have groups with overlapping privileges. To accommodate this, you may need to implement several sets of passwords and allow one or more passwords to unlock particular programs. But again, if a user is transferred from say, payroll to general ledger, you would probably have to reissue new passwords to the payroll group.

The ultimate solution to these problems is to implement a custom security mechanism within the application that allows both programs and functions within programs (such as delete vs. add), to be restricted by user (or perhaps even category of user), which many applications have done. The problem with the latter solution is simply that it involves significant modifications to all of the programs in the application. And to some extent, it requires duplicating a lot of engineering which has already gone into the operating system, as well as requiring the maintenance of two sets of user logins and passwords (one for the operating system and one for the application).

For those seeking something in the middle, i.e. more flexibility than the former approach and less effort than the latter, A-Shell offers a capability which leverages the file access privilege mechanisms of the host operating system and requires minimal programming. The first step is to issue individualize logins and passwords to all users. Then, define groups which correspond to access privileges, such that a user’s ability to run a particular program can be controlled by whether the user is a member of a particular group. Finally, change the access privileges on all of the programs in the application so that each program is owned by the appropriate group, and that read access is denied except to members of that group.

Under UNIX, use the chown or chgrp utilities to change group ownership, and the chmod utility to set individual access bits on a file. (Note that directories must have the execute bit set! RUN and LIT programs need only read access. Data files need read and write access.) Under Windows, you can set the privileges by right-clicking on the file.

When A-Shell attempts to access a RUN or LIT program for which the current effective user does not have read privileges (i.e. which is owned or associated with a group to which the user is not a member), it will abort to the "dot prompt" with an "access denied" error. This fact alone provides the necessary security for the scheme just described to work, but aborting to the dot prompt with an error message is hardly a graceful way to deny unauthorized access. A better approach would be to automatically redirect the user to another program, perhaps the main menu of the application, or better yet, an error recovery program, which explained that the user was not authorized, and then chained to a central menu. MX_CHAINTO, allows you to define just such a program. Since this definition persists for the duration of the A-Shell session, it can be established in a startup program within touching any of the application’s existing programs.

To illustrate this, consider the case of an application that starts from a command file main.cmd, which logs the user in and starts the main menu, MENU1.RUN. We’ll create a simple standalone program, called ACCERR, to implement the access trap, and insert it into the main.cmd as follows:

;MAIN.CMD - Application startup

;Log to the application directory…

LOG APP:

;Set up a handler for access violations…

RUN APP:ACCERR INIT

;Start the application main menu

:R

RUN MENU1

The program, ACCERR, might look something like the sample below. Note that to combine its two modes into a single program, we allow the use of a single command line argument ("INIT", as shown in the command file above). When the argument is specified, the program just initializes the access trap using MX_CHAINTO and then exits. Otherwise, we assume we have been called because a user tried to run an unauthorized program, in which case we display a message before chaining to the main menu.

!ACCERR.BAS - Handler for unauthorized attempts to run programs

map1 CLINE,S,80

map1 X,F

 

!Pick up the command line (program name and argument).

xcall LSTLIN,CLINE    ! (e.g. "APP:ACCERR INIT")

 

!If "INIT" arg specified, initialize access trap to point to

!this program (whose name is the first arg on command line)

X = instr(1,ucs(CLINE)," INIT")

if X > 0 then

xcall MIAMEX,MX_CHAINTO,1,CLINE[1,X-1]

END

endif

 

!Otherwise, we came here because the user tried to run a program

!which was unauthorized. Display a message and chain to the menu

 

print "Sorry, you do not have access to run that program."

input "Hit ENTER to return to the main menu: ",A

 

chain "MENU1"

By taking advantage of the operating system’s capabilities for assigning users to groups and relating file access rights to group membership, the simple scheme just described provides a sophisticated access controls within the application, without requiring changes to the application. For many applications, this will be sufficient, and may even eliminate the need to implement a login capability within the application. (You can retrieve the user’s operating system login via GETUSN.SBR.)

Note, however, that this scheme cannot, by itself, provide a way to limit access to functions within a program (such as to permit anyone to add a record but only certain people to delete.) However, it can simplify the implementation of such a capability. For example, rather than define a database of which users have access to which functions within the application, and a special data entry program to manage that database, you might instead simply create a series of dummy control files associated with function names (e.g. "add.sys", "delete.sys", etc.) and use the access system described above to set appropriate privileges for those files. The application could then determine if a user has access to a particular function by seeing if the user can open the corresponding control file. This would require that you use an ON ERROR GOTO to trap the error that would occur when attempting to open a file to which you didn’t have access rights.