#!/bin/sh # # This is a shell archive. To extract its contents, # execute this file with /bin/sh to create the file(s): # # Makefile app appstart.c tech_paper.txt # README # # This shell archive created: Wed Jul 22 10:50:33 EDT 1992 # echo "Extracting file README" sed -e 's/^X//' <<\SHAR_EOF > README XREADME X XThis collection of files demonstrates one way of controlling user permissions Xin Informix applications by running them setuid. The files are: X X README this file X X appstart.c the source for the front-end application start-up program X X Makefile a sample Makefile for compiling and installing appstart X X app a sample shell script that the user would run to invoke X the application X X tech_paper.txt an ASCII version of the technical paper on this subject X presented at the 1992 Informix Worldwide User Conference X X XFor this technique to work, appstart must be installed setuid to root. You Xshould be intimately familiar with the issues related to such processing before Xyou attempt to use this technique. X XThe file appstart.c is a generic version of a program currently in production Xuse. Since the main purpose of appstart.c is to demonstrate the technique, Xcode not directly related to the setuid process has been removed. This Xincludes code that would be important in a production version, such as Xstatements that check for error status or buffer overflow. X XThe file tech_paper.txt contains an ASCII version of the technical paper as it Xwas presented at IWUC92. There are several considerations that were not Xexplored in detail in the paper due to length and time constraints. X XOne possible variation of this scheme might be to run only the back-end Xdatabase engine setuid using this technique. This has been suggested, but I Xhave yet to try this approach. It should work, though, and would have the Xadvantage that the front-end would still be running as the invoking user. XThis would make operations like working with Unix files from within the Xapplication much easier. X XAn indication that this approach might not be appropriate in all environments Xis the problem of running setuid programs that use shared libraries. This has Xnot been a factor under SunOS 4.1.x, probably because to date Informix Xexecutables do not use shared libraries in that environment. However, this Xmay become a problem in future releases of Informix or SunOS. X XIf you have any questions, or especially if you notice any potential problems Xwith using this technique, feel free to contact me. X X XWalt Hultgren XJuly, 1992 X X-- XWalt Hultgren Internet: walt@rmy.emory.edu (IP 128.140.8.1) XEmory University UUCP: {...,gatech,rutgers,uunet}!emory!rmy!walt X954 Gatewood Road, NE BITNET: walt@EMORY XAtlanta, GA 30329 USA Voice: +1 404 727 0648 SHAR_EOF if [ `wc -c < README` -ne 2561 ] then echo "Lengths do not match -- Bad Copy of README" fi echo "Extracting file Makefile" sed -e 's/^X//' <<\SHAR_EOF > Makefile X# Makefile Makefile for appstart.c X# X# X# (c) Copyright 1992 by X# X# Yerkes Research Center of Emory University X# Atlanta, Georgia, U.S.A. X# X# All Rights Reserved. X# X X X# X# Set directory where start-up program should be installed. X# X XSTARTDIR = /usr/local/lib X X X# X# Set application environment variables. X# X XAPPBASEDIR = /user/app X XAPPBIN = $(APPBASEDIR)/bin X XAPPPATH = /usr/ucb:/bin:/usr/bin/:/usr/local/informix/bin:$(APPBIN) X XAPPSHELL = /bin/sh X X X# X# Build the define's for the compile X# X XDBPATH = $(APPBASEDIR):$(APPBASEDIR)/frm:$(APPBASEDIR)/help X XENVDEF = -DPREFIX=\"a_\" \ X -DSETPATH=\"PATH=$(APPPATH)\" \ X -DSETDBPATH=\"DBPATH=$(DBPATH)\" \ X -DSETSHELL=\"SHELL=$(APPSHELL)\" \ X -DAPPBINDIR=\"$(APPBIN)\" X XCFLAGS = -O X Xappstart : appstart.c Makefile X $(CC) $(CFLAGS) $(ENVDEF) $(SYSDEF) appstart.c -o $@ X Xinstall : appstart X install -o root -g appgrp -m 4110 appstart $(STARTDIR) SHAR_EOF if [ `wc -c < Makefile` -ne 1010 ] then echo "Lengths do not match -- Bad Copy of Makefile" fi echo "Extracting file app" sed -e 's/^X//' <<\SHAR_EOF > app X#!/bin/sh X# X# app Start the application from the shell X# X# X# (c) Copyright 1992 by X# X# Yerkes Research Center of Emory University X# Atlanta, Georgia, U.S.A. X# X# All Rights Reserved. X# X X X# X# Set application shell variables for this user X# X Xif [ -f $HOME/.apprc -a -r $HOME/.apprc ] Xthen X . $HOME/.apprc Xfi X X X# X# Initialize important shell variables X# X XINFORMIXDIR=/usr/local/informix Xexport INFORMIXDIR X X X# X# Replace this process with application start-up process X# X Xexec /usr/local/lib/appstart SHAR_EOF if [ `wc -c < app` -ne 592 ] then echo "Lengths do not match -- Bad Copy of app" fi echo "Extracting file appstart.c" sed -e 's/^X//' <<\SHAR_EOF > appstart.c X/* appstart.c Start an Informix application from the shell X * X * X * (c) Copyright 1992 by X * X * Yerkes Research Center of Emory University X * Atlanta, Georgia, U.S.A. X * X * All Rights Reserved. X * X * X * This file contains the source for a prototype of the program "appstart" X * described in the paper "Varying Informix Database Permissions by X * Application Under Unix" presented at the 1992 Informix Worldwide User X * Conference (IWUC92). X * X * This version of appstart.c should compile and execute under a BSD-based X * Unix. However, it should not be considered suitable for production use X * since its primary purpose is to demonstrate the technique described in X * the paper. Code that is essential to safe operation, but is not directly X * related to setuid proccessing, has been removed. X * X * No responsibility can be assumed for any use made of the information X * contained in this file. If you utilize this technique in an end-user X * application, you should at minimum be very familiar with the concepts X * of C programming and running setuid in your particular environment. X * X */ X X X#include X#include X#include X#include X#include X#include X X X#ifdef lint X X#define PREFIX "" X#define SETDBPATH "" X#define SETPATH "" X#define SETSHELL "" X#define APPBINDIR "" X X#else X X static char SCCS_ID[] = "%Z% %M% %I% %G% %U%"; X X#endif X X X#define MAXSTR 256 X X/* Globals & Start of main() */ X X X char *this_prog; /* name of this program for error messages */ X X char *app_bin = APPBINDIR; /* menu directory pathname */ X char app_path [ MAXSTR ]; /* full pathname of application program */ X char inv_home [ MAXSTR ]; /* invoking user-ID's home directory */ X char apprptdir [ MAXSTR ]; /* report directory environment entry */ X X Xmain ( argc, argv ) X X int argc; X char *argv[]; X X { X X void err_exit(); X X struct passwd *pwentry; /* pointer to a passwd entry */ X X char app_login[9]; /* application login-ID - 8 chars max + NULL */ X X X /* Save name of this program for error messages */ X X this_prog = argv[0]; X X /* X This section gets the passwd entries for the invoking user-ID and its X corresponding application user-ID. It then sets the real and effective X group and user ID's to be those required for the application. X */ X X X /* Get passwd entry for invoking uid & save home directory pathname */ X X if ( ( pwentry = getpwuid ( getuid() ) ) ) X { X strncpy ( inv_home, pwentry->pw_dir, MAXSTR ); X } X else X { X err_exit ( "cannot get your passwd file entry" ); X } X X X /* Construct application login-ID from invoking login-ID */ X X strncpy ( app_login, PREFIX, 8 ); X strncat ( app_login, pwentry->pw_name, ( 8 - strlen ( PREFIX ) ) ); X X app_login[8] = '\0'; /* just in case */ X X X /* Get passwd entry for application login-ID */ X X if ( ! ( pwentry = getpwnam ( app_login ) ) ) X { X err_exit ( "cannot get your passwd file entry for this application" ); X } X X X /* Insure password entry for application login-ID is "*" */ X X if ( strcmp ( pwentry->pw_passwd, "*" ) ) X { X err_exit ( "invalid application entry in passwd file" ); X } X X X /* Set real and effective gid's required to run application */ X X if ( setregid ( pwentry->pw_gid, pwentry->pw_gid ) ) X { X err_exit ( "error setting application group-ID" ); X } X X X /* Set real and effective uid's required to run application */ X X if ( setreuid ( pwentry->pw_uid, pwentry->pw_uid ) ) X { X err_exit ( "error setting application user-ID" ); X } X X /* X This section sets up the application environment and exec's the X application program with any arguments supplied to this program. X */ X X X /* Set important environment variables here for security */ X X putenv ( SETDBPATH ); X putenv ( SETPATH ); X putenv ( SETSHELL ); X X X /* Set application report directory pathname in environment */ X X strcpy ( apprptdir, "APPRPTDIR=" ); X strcat ( apprptdir, inv_home ); X strcat ( apprptdir, "/appreports" ); X X putenv ( apprptdir ); X X X /* Build full application program pathname */ X X strcpy ( app_path, app_bin ); X strcat ( app_path, "/" ); X strcat ( app_path, pwentry->pw_shell ); X X X /* Set the default file creation permission mask to eliminate */ X /* group and other permissions and user execute permission */ X X umask ( 0177 ); /* note constant is octal */ X X X /* Set arg0 for the exec to be the name of the application program */ X X argv[0] = pwentry->pw_shell; X X X /* exec the application program with arguments from invoking argv[] */ X X execv ( app_path, argv ); X X X /* If we get here, the exec failed */ X X err_exit ( "error starting application" ); X X X } /* End of main() */ X X/* err_exit Print error message and exit */ X X Xvoid err_exit ( msg ) X X char *msg; /* error message */ X X { X X /* Display error message on stderr and exit */ X X fputs ( this_prog, stderr ); X fputs ( ": ", stderr ); X fputs ( msg, stderr ); X fputs ( "\n", stderr ); X X exit ( ( errno ? errno : 1 ) ); X X } SHAR_EOF if [ `wc -c < appstart.c` -ne 5391 ] then echo "Lengths do not match -- Bad Copy of appstart.c" fi echo "Extracting file tech_paper.txt" sed -e 's/^X//' <<\SHAR_EOF > tech_paper.txt X X X Varying Informix Database Permissions by Application Under Unix X X X Walt Hultgren X X Yerkes Research Center X Emory University X X X --------------------------------------------------------- X XABSTRACT: It is often desirable for a Unix user to have different permissions Xwithin an Informix database under different circumstances. One solution to Xthis problem is to run each Informix application setuid to an alternate Xuser-ID. The alternate user-ID is granted permissions appropriate for the user Xin that application. This approach provides each user with a unique set of Xpermissions for each of several Informix applications, all of which may be run Xfrom a single login-ID. Such a scheme may be implemented using standard Unix Xauthentication routines, which allows it to be added to existing applications Xwithout requiring additional programming or database operations. X X --------------------------------------------------------- X X X X 1. Introduction X XInformix provides a mechanism for granting a Unix user access permissions Xwithin a database. However, it is often desirable for a user to have different Xsets of permissions within the same database under different circumstances. X XA common example is a site where users update a database using an Informix-4GL X(I4GL) application, but want to perform SQL queries against the same database Xusing Informix-SQL (ISQL). Users who are permitted to update tables under the Xcontrol of I4GL programs should not have update permission in the less restric- Xtive ISQL environment. X XIn some situations, user access can be controlled by creating different views Xof the database. However, this scheme may be difficult to administer, and may Xreduce performance. Assigning each user a separate login-ID for each applica- Xtion is another possible approach, but is cumbersome for end-users. X XOne solution is to run each Informix application setuid to an alternate Xuser-ID. The alternate user-ID is granted permissions appropriate for the user Xin that application. For this scheme to be most effective, each user must have Xindividualized database permissions for each of the applications involved. X XSimply installing application programs with setuid permission will not suffice Xfor several reasons. Foremost is the fact that setuid permission changes only Xthe effective user-ID when a file is executed. Informix uses the login name Xderived from the real user-ID to assign permissions. X XThus, a facility is required that determines an alternate login name based on Xthe invoking login name and the application being run. X X X X X X X X X X X X X X X X X 2. Terms and Definitions X XIn this text, the term "login name" refers to the string of characters entered Xto log into the system. The term "user-ID" means the integer used internally Xby Unix to identify the user. X XThe "invoking" user-ID is the one under which a user is running when an appli- Xcation is invoked, usually from the shell. The "application" user-ID is the Xalternate user-ID under which the application is ultimately run. X XAll other terms are used in accordance with standard Unix definitions. X X X X 3. Overview X XInformix allows one set of permissions in a database for each login name on the Xsystem. When an application attempts to access an Informix database, the login Xname under which the process is running determines the permissions granted to Xthe program. X XIt is unreasonable to expect the DBA to grant new permissions each time a user Xwants to run a particular application against the database. An alternate Xapproach is to make the user appear to Informix to have a different login name Xduring the application run. The DBA may then grant the required permissions to Xthe login name under which the application will be run. X XSince Informix grants user permissions based on the login name rather than the Xuser-ID, the application login name must be entered in the passwd file. When Xthe user invokes the application, a small start-up program that is setuid to Xroot may be run to set the real user-ID to the value that corresponds to the Xapplication login name, then pass control to the application. X XThis technique allows a user to run one or more Informix applications from a Xsingle shell-level login while having individualized database permissions in Xeach of those applications. There are several benefits to this approach: X X o Different permission sets can be granted to a user for different applica- X tions run against the same or different databases from a single shell- X level login. X X o The start-up processing doesn't directly interact with the Informix appli- X cation itself and can be retrofit into existing systems fairly easily. X X o The executable that is setuid to root is a small C program for which X source code is maintained locally. It isn't necessary to make any of the X application programs setuid. X X o Native Unix user validation routines are used. This automatically extends X the facility across a networked environment such as NIS/YP. X X X X X X X XVarying Informix Permissions 2 X X X X X X X X X 4. The Start-Up Program X XThe application start-up program must perform several functions. It must set Xthe required application user-ID, initialize the execution environment, and Xfinally pass control to the application. X XSuch a program will be described in this text and called "appstart" for discus- Xsion purposes. A complete source listing of appstart will not be provided. XHowever, the functional elements of the program will be discussed, and sample C Xcode and file fragments will be presented that are designed to operate under a Xversion of Unix based on BSD 4.x. X XA separate copy of appstart is tailored and compiled for each application. The Xresulting executable is then installed setuid to root. It is situated so that Xwhen a user invokes the application, it is appstart that is first run. X XWhen appstart is run, it obtains the invoking user's login name based on the Xreal user-ID. From this, the program generates the login name under which to Xrun the application for that user. This is done by adding a prefix string to Xthe invoking login name. The prefix is different for each application on the Xsystem. X XThe program next retrieves the passwd entry for the generated application login Xname. The real and effective group and user ID's are set to those found in the Xpasswd entry for the application login name. X XThe C code fragment shown in Figure 1 will perform these steps. X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X XVarying Informix Permissions 3 X X X X X X X X X X struct passwd *pwentry; /* pointer to a passwd entry */ X char app_login[9]; /* application login name - 8 chars + NULL */ X X X /* Get passwd entry for invoking user-ID */ X X if ( ! ( pwentry = getpwuid ( getuid() ) ) ) exit(1); X X X /* Construct application login name from invoking login name */ X X strcpy ( app_login, "a_" ); X strncat ( app_login, pwentry->pw_name, 6 ); X app_login[8] = ' '; /* just in case */ X X X /* Get passwd entry for application login name * X X if ( ! ( pwentry = getpwnam ( app_login ) ) ) exit(1); X X X /* Insure password entry for application login name is "*" */ X X if ( strcmp ( pwentry->pw_passwd, "*" ) ) exit(1); X X X /* Set real and effective group-ID's required to run application */ X X if ( setregid ( pwentry->pw_gid, pwentry->pw_gid ) ) exit(1); X X X /* Set real and effective user-ID's required to run application */ X X if ( setreuid ( pwentry->pw_uid, pwentry->pw_uid ) ) exit(1); X X XFigure 1: A code fragment that will perform setuid processing in appstart. X X X XAfter the call to setreuid(2), appstart is no longer running as root. It Xshould then initialize the environment required by the application. Noncriti- Xcal environment variables may be set and exported at the shell level prior to Xrunning appstart. These settings will carry across the setuid processing. X XImportant variables such as PATH and SHELL should be set within appstart to Xguarantee that they have appropriate values for the application. This is usu- Xally done with a system library function such as putenv(3) or setenv(3). The Xname of this routine and the arguments it requires are platform-dependent. X XThe final task of appstart is to pass control to the application by executing Xthe specified application program using one of the library function interfaces Xto the execve(2) system call such as execl(3) or execv(3). X X X XVarying Informix Permissions 4 X X X X X X X X X 5. passwd File Entries X XIn addition to the usual passwd entries that grant system access to the various Xusers, an entry must be created for each application login name. These entries Xhave the same form as a normal passwd entry, but several of the fields contain Xspecial values. X XIn an application passwd entry, the login name should be generated by con- Xcatenating the prefix string for the application and the invoking login name. XThe resulting string should be truncated to 8 characters. This login name must Xbe unique like any other on the system. X XThe password field should be set to prevent direct login's to the application Xlogin name. This is usually done by placing a string such as "*" or "no login" Xin the password field. X XThe user-ID and group-ID should be set to the values to be used during the Xapplication run. In most circumstances, the application user-ID should be Xunique like any other user-ID. It is best to create a separate Unix group for Xthe application to further control access. X XThe GCOS field of the application passwd entry is not used by appstart, and may Xbe set according to local procedures. X XStrictly speaking, the home directory field is also unused by appstart. How- Xever, since the application user-ID is a valid Unix ID, other utilities may Xexpect it to have a home directory. Some provision must be made for forwarding Xe-mail to the invoking user that is inadvertently addressed to the application Xlogin name. This may involve placing a ".forward" file in a home directory Xcreated for the application login name if the system mailer operates in that Xmanner. X XThe seventh passwd field should contain the name of the application program to Xbe started by appstart. Typically, appstart will have the application bin Xdirectory pathname hard-coded into the executable for increased security. The Xfull pathname for the application program is built at run-time by combining the Xprogram name in the passwd entry with the hard-coded directory. X XFigure 2 shows sample passwd entries for a user's invoking and application Xlogin names. X X walt:xxxxxxxxxx:201:101:Walt Hultgren:/users/walt:/bin/ksh X a_walt:*:202:201:Walt Hultgren:/apphome/a_walt:appmenu.4ge X X XFigure 2: Sample passwd entries for a user's invoking and application login X names. X X X X X X X X X X XVarying Informix Permissions 5 X X X X X X X X X 6. Authorizing Application Users X XTo grant a user access to an application, the system administrator must create Xthe passwd entry for the user's application login name, and set up any required XUnix directories. The DBA must then grant the appropriate database permissions Xto the application login name. X XIf the application allows users to capture reports to disk or otherwise create Xfiles, a potential conflict arises from the fact that such files must be viewed Xunder the invoking user-ID and group-ID, which are different from the applica- Xtion ID's that created them. Since such files may contain confidential infor- Xmation, simply giving them global read/write permission is unwise. X XTo solve this problem, such files should be placed in a separate directory Xcreated specifically to hold output from the application for the user. This Xdirectory must be in a parent directory that is searchable by the application. X XThe holding directory is created so that it is owned by the invoking login Xname, and assigned to the application group-ID. Permissions on the directory Xshould be 730. Note that this operation must be performed as root, since no Xshell-level users are allowed in the Unix group used by the application. X XThe application should force all output files into the special holding direc- Xtory. The permissions on such files should be 604. This will allow the invok- Xing user to read and remove the files from the shell level. X X X X 7. Limitations and Other Considerations X XThis method of controlling access to an Informix database is intended to be Xused with a relatively closed application system. That is, the program that Xappstart runs should be the top-level menu program for the application. That Xprogram may run other programs, but the user should always be "locked into" the Xapplication. X XThe application may be comprised of a combination of user-compiled programs, Xshell scripts and standard Unix utilities. However, the application's design Xshould take into account the fact that it will be running setuid. X XAllowing escape to the shell from within the application is strongly Xdiscouraged. If a utility is used that allows "banging-out" to the shell, that Xfeature should be disabled by setting the value of the SHELL environment vari- Xable appropriately when that utility is invoked. X XThe consideration that this technique involves running a collection of programs Xsetuid should not be minimized. Every effort must be made to insure that the Xapplication programs and utilities behave correctly in a setuid environment. X XOther aspects of this technique may limit the environments in which it may be Xsuccessfully used. X X o Each application user-ID must be in the passwd file (or NIS/YP). This X could be a problem for sites approaching the upper limit on the number of X X X XVarying Informix Permissions 6 X X X X X X X X X users. X X o Some of the set-up processing done to authorize each user for an applica- X tion must be done as root. This includes changing the passwd file and X possibly creating some directories. X X o There may be additional design considerations for the application that X arise from the fact that it is running setuid from the shell. Some areas X to consider are printer and process control, environment variables, and X utilities that allow escape to the shell. X X o The name of the application program is kept in the shell field of the X passwd record for the application user-ID, which means everyone can see X it. This might be a problem in some situations. X XThe technique of running setuid is not appropriate for every application, and Xit is certainly not advisable for inexperienced system support personnel. How- Xever, in a controlled environment it can be used effectively to allow multiple Xusers to have individualized permissions in multiple applications run against a Xsingle Informix database. X X X X Acknowledgments X XHarry Bochner, John R. Carter, Sr., Tony Heskett and Jonathan Leffler provided Xcritical commentary on the implementation of this technique and the code and Xfile fragments used to demonstrate it. Acknowledgment is made of support from Xthe Yerkes Research Center of Emory University, NIH Grant Number RR-00165. X X X X X Copyright 1992 by Walt Hultgren - All Rights Reserved. X X X X X X X X X X X X X X X X X X X X X X X XVarying Informix Permissions 7 X X SHAR_EOF if [ `wc -c < tech_paper.txt` -ne 15569 ] then echo "Lengths do not match -- Bad Copy of tech_paper.txt" fi echo "Done."