Chat now with support
Chat with Support

Safeguard for Sudo 2.0 - Administrators Guide

One Identity Privileged Access Suite for Unix Introducing Privilege Manager for Unix Introducing Privilege Manager for Sudo Planning Deployment Installation and Configuration
Download Privilege Manager for Unix Software Packages Download Privilege Manager for Sudo Software Packages Quick Start and Evaluation Configure a Primary Policy Server Configure a Secondary Policy Server Install PM Agent or Sudo Plugin on a Remote Host Remove Configurations
Upgrading Privilege Manager System Administration Managing Security Policy The Privilege Manager for Unix Security Policy Advanced Privilege Manager for Unix Configuration Administering Log and Keystroke Files InTrust Plug-in for Privilege Manager Troubleshooting Privilege Manager for Unix Policy File Components Privilege Manager Variables Privilege Manager for Unix Flow Control Statements Privilege Manager for Unix Built-in Functions and Procedures Privilege Manager Programs Installation Packages Unsupported Sudo Options Sudo Plugin Policy Evaluation About us

Example 8: Control the Run-Time Environment

This example demonstrates how you can set up a particular job's run-time operating environment with Privilege Manager. Although the policy fragments shown below are arbitrary, you can use similar fragments to implement your own policies.

Type the following fragment into the /etc/opt/quest/qpm4u/policy/pm.conf file, or copy it from the examples directory in the Privilege Manager distribution directory. Replace "dan" and "robyn" with users from your site.

NOTE: Do not type in the line numbers.

1 # Run-time example configuration file 
2    adminusers={"dan", "robyn"}; 
3    adminprogs={"ls", "hostname", "kill", "csh", "ksh", "echo"}; 
4    if(user in adminusers && command in adminprogs) { 
5       if(!(cwd=="/usr" || glob("/usr/*", cwd)) 
6          runcwd="/tmp"; 
7       if(argc > 2) 
8          runargv=range(argv, 0, 2); 
9    runuser="root"; 
10    rungroup="bin"; 
11    if(command!="hostname") 
12       runhost=submithost; 
13    keepenv("TERM", "DISPLAY", "HOME", "TZ", "PWD", "WINDOWID", "COLUMNS", "LINES"); 
14    setenv("PATH", "/usr/ucb:/bin:/usr/bin:/usr/local/bin:/usr/bin/X11:" + 
15    "/usr/X11/bin:/usr/etc:/etc:/usr/local/etc:/usr/sbin"); 
16    safeshells={"/bin/sh", "/bin/csh", "/bin/ksh"}; 
17    if(getenv("SHELL") in safeshells) 
18       setenv("SHELL", getenv("SHELL")); 
19    else 
20       setenv("SHELL", "/bin/sh"); 
21    runumask=022; 
22    runnice=-4; 
23    accept; 
24    }

The following describes the results of this example:

  • Lines 5, 6

    These lines designate in which directory the job will run. Line 5 checks the current working directory: if the cwd variable is /usr or if it glob-matches "/usr/*", the request will execute under that directory. If not, the request will execute in /tmp.

  • Lines 7, 8

    In this example, no more than two arguments are allowed to be specified to the requested command. The range function in line 8 returns all arguments and only the first three elements of the argv list (element 0, which is the command name; element 1, the first argument; and element 2, the second argument).

  • Line 9

    This line causes the request to run as root.

  • Line 10

    This line causes the request to run as the bin group.

  • Line 11, 12

    These lines specify that if the command is not hostname, run it on the machine from which the request was submitted. If the command is hostname, run it on whatever machine the user wishes. (By default, it will run on the machine from which the request was submitted; you can change this using the -h argument to pmrun.)

  • Line 13

    First, line 13 deletes all environment variables, except those specified in the keepenv list. Since you can use environment variables to exploit security holes in UNIX® programs and shell scripts, be careful when specifying the environment variables for a request.

  • Line 14

    This line sets the PATH variable explicitly to include only safe directories. Note the use of the + operator to concatenate the values assigned to the PATH variable; + splits the values over two lines to avoid ugly end-of-line wrapping.

  • Line 15-19

    This fragment ensures that the SHELL variable is only set to a safe value. If the existing SHELL variable is already set to one of the values defined as "safe" in safeshells, then that value is used. If not, then the SHELL is set to /bin/sh.

    NOTE: getenv reads from the env variable; setenv and keepenv write to the runenv variable.

  • Line 20

    This line sets the command's umask value to 022: data files created by the command will have rw-r--r-- permissions, and directories will have rwxr-xr-x permissions. Since the command will run under the root account, root will own the files.

    NOTE: Specify a leading zero when typing in umask values so they are interpreted as octal numbers.

  • Line 21

    The command will run with a nice value of -4, which gives it a high priority relative to other jobs on the system.

  • Line 22

    After setting up the job’s environment, the request is accepted and the job is run.

Check the configuration file for errors with pmcheck. (For more information about using pmcheck, see Example 1: Basics.)

Try running your favorite shell, for example:

# pmrun csh

In the shell, you can then enter env to list the environment variables, pwd to print the working directory in which your request ran, or umask to display the umask value.

Example 9: Switch and Case Statements

The following example illustrates how you can use the switch and case statements to implement complex policies. In this case, different users act as system administrators on different days of the week.

Type this fragment into the /etc/opt/quest/qpm4u/policy/pm.conf file, or copy it from the examples directory in the Privilege Manager distribution directory. Replace "dan", "robyn" and "cory" with users from your site.

adminprogs={"ls", "hostname", "kill", "csh", "ksh", "echo"}; 
if(command in adminprogs) { 
switch (dayname) { 
   case "Mon": true; 
   case "Wed": true; 
   case "Fri": adminusers={"dan", "robyn"}; 
      break; 
   case "Tue": true; 
   case "Thu": adminusers={"robyn", "cory"}; 
      break; 
   default: adminusers={}; 
} 
if (user in adminusers) { 
   runuser="root" 
   accept; 
}

When entering a switch statement, execution immediately jumps to the first case statement that matches the argument to switch (in this case, dayname). Execution proceeds from that point until a break statement or the end of the switch is reached. When a break statement is reached, execution jumps immediately to the end of the switch. If no case matches the argument to switch, execution jumps to the default statement.

NOTE: Once execution has jumped to a case statement, it is unaffected by subsequent case statements. Only a break causes execution to jump to the end of the switch statement. If you omit a break, execution falls through to the next case statement.

Check the configuration file for errors with pmcheck. (For more information about using pmcheck, see Example 1: Basics). Log in as one of the adminusers to see if you can run requests with pmrun (it will depend on the current day). (See switch for further details.)

Example 10: Menus

This example shows you how to present the commands a user may access as root in a menu by implementing a menu system with four choices. If the user selects the first menu item, he is asked to correctly type in a password before Privilege Manager runs the adduser program. If the user selects menu items b, c or d, Privilege Manager runs the backup, file ownership or line printer administration programs.

If the user’s request is accepted and executed, Privilege Manager prints messages to the user’s screen specifying the requested command and user under which the command will run. If the user makes an invalid menu choice, Privilege Manager prints a warning message and rejects the request.

Type the following code fragment into the /etc/opt/quest/qpm4u/policy/pm.conf file, or copy it from the examples directory in the Privilege Manager distribution directory. Replace "dan", "robyn", and "cory" with users from your site.

if(command=="adminmenu") { 
   print("========= Admin Menu ========="); 
   print("a) Add users"); 
   print("b) Start a backup"); 
   print("c) Change ownership of a file"); 
   print("d) Fix line printer queues"); 
   choice=input("Please choose one: "); 

   switch(choice) { 
      case "a": 
      # Reject the request if the password "123456" is not entered 
      # correctly. The user is allowed only two chances to type 
      # the password correctly. The encrypted version of the 
      # password seen here was generated using "pmpasswd". 
      # If you store encrypted passwords in your config file, 
      # make sure you turn off read permission on the file so 
      # that no one can use a password cracking program to 
      # guess them. 
         if(!getstringpasswd("m9xxg7B4.v8Ck", 
               "Type in the adduser password: ", 2)) 
            reject; 
         runcommand="/usr/local/bin/adduser"; 
         runuser="root"; 
         break; 
      case "b": 
         runcommand="/usr/local/bin/dobackup"; 
         runuser="backup"; 
         break; 
      case "c": 
         runcommand="/etc/chown"; 
         runuser="root"; 
         break; 
      case "d": 
         runcommand="/usr/lib/lpadmin"; 
         runuser="root"; 
         break; 
      default: 
         printf("\"%s\" was not a valid choice.Sorry.\n", choice); 
      reject; 
} 
   print("** Command to be run :", runcommand); 
   print("** User to run command as :", runuser); 
   accept; 
   }

Check the configuration file for errors with pmcheck. (For more information about using pmcheck, see Example 1: Basics).

To display the menu, enter:

# pmrun adminmenu

Select the first menu item. When Privilege Manager asks you for the password, type "123456". Privilege Manager accepts the request and attempts to execute the job.

NOTE: Since the commands in this example probably do not exist on your system, the job will fail. Try substituting your own commands in each of the menu items, and test the fragment again.

Use the While Loop

To create more complex statements in the configuration file, you can use a while loop construction. For example:

while (expression) { 
   <script statements>; 
}

In the following example, the scripting language searches the argument list of the command for the argument root. This is useful for allowing access to the passwd command.

count=1; 
while( count < argc ) { 
   if( argv[count] == "root" ) 
   reject; 
   count=count+1; 
}

(See while for further details.)

Related Documents