Previous Topic

Next Topic

Control Access to Data with Staid (UNIX)

The UNIX Setuid bit can be used to control access to data, without needing to issue grants to specific users or the public. This technique allows a user to operate on the data, but only when the user has accessed it through a specific application program. The data is otherwise inaccessible to the user. After the user has exited the program, the user cannot access this same data using any Ingres utility.

Previous Topic

Next Topic

Use Chmod to Set the Setuid Bit

After an embedded SQL application program has been created, the permissions of the program file can be set so that it can run with the effective user ID set to that of the owner of the file. If, for example, the owner of the file is the DBA, any user executing the program is recognized as the DBA—and has the same access to objects and data as the DBA—for the life of the program.

The UNIX chmod command issued at the operating system prompt is used to change the mode of a file. The following format of this command changes the mode of the specified file name to give "set user id on execution" and "execute" permission to everyone. The 4 sets the Setuid bit:

chmod 4711 filename

For example, if the following command is executed:

chmod 4711 app1prog

The resulting file permissions looks like this:

-rws--x--x 1 dba 7584 Mar 30 app1prog

Using this technique, the DBA (or other user, such as an application developer) can allow any user to temporarily become the effective user id for controlled access to specific application programs. The effective user ID is recognized when a connection is made to the Ingres DBMS Server.

Note: Only the application owner or the root user can run the chmod operating system command.

Previous Topic

Next Topic

Example: Refer to Setuid in an Embedded SQL Application

An example is shown here that can be used in embedded SQL application programs that are made accessible by the Setuid bit. It checks that the connections are in place before allowing the program to be run.

The program requires that the login of the program owner be known (in this case, fred, defined in line 2. It uses the UNIX getpwnam function to fetch the effective user ID from the passwd structure. For details, see the UNIX documentation.

The program checks to see if the caller can access the database, printing an error message if not. This can occur, for example, if a chmod command has not been issued on the application program, as described in the previous section.

The application code appears between the connect and disconnect statements. In the sample code that follows, the action of the program is to print the effective user ID:

#include  <pwd.h>

#define   DBA       "fred"

/*  Example to demonstrate how to run an embedded SQL program 

** in such a way that there is no requirement for the users to have 

** privileges on the tables accessed by the program.

**

**  This example assumes the program will access tables owned by the 

**  DBA, but this scheme could be used for any user. Additionally, assume 

**  the DBA has granted no privileges.

**

**  This program checks that it is running setuid to the DBA.

** If it is, it does a database connect.

** If it is not running setuid to the DBA, 

**  it gives an error message to the user and exits.

** This check is done simply as a convenience to the user.

**  If this check isn't done and the user is a valid INGRES user, 

**  he or she can still connect to the database, 

** but will not be able to access any of the data.

**  This would be frustrating to the user, 

**  so the program stops them before they get connected.

**

**  For this scheme to work, the executable MUST be setuid to the DBA.

*/

main()

{

  EXEC SQL begin declare section;

    char  username[32];

    char  dbname[32];

  EXEC SQL end declare section;

  int   user;

  int   ret_val = 0;

  struct  passwd   *getpwnam();

  struct  passwd   *password_entry;

  password_entry = getpwnam(DBA);

  /* Check to see if the user interface is running setuid 

** to the dba (fred).

  ** If not, give the user a message and abort.

  ** If so, connect to the database.

  */

  if ((user = geteuid()) != (password_entry->pw_uid))

  {

    printf("Error starting application. Contact the DBA.\n");

    ret_val = 1;

    exit(ret_val);

  }

  EXEC SQL connect dbname;

  /* The following query will demonstrate that the dbms connection 

  ** was done by user fred, not the actual user.

  */

  

EXEC SQL select username() into :username;

  printf("User is %s\n", username);

  EXEC SQL disconnect;

}


© 2007 Ingres Corporation. All rights reserved.