Pegasus Enhancement Proposal (PEP)
PEP #: 286
PEP Type: Functional
Title: Privilege Separation
Status: Approved
Version History:
Version | Date | Author | Change Description |
---|---|---|---|
1.0 | 2006-11-13 | Michael Brasher | First Draft |
1.1 | 2006-12-16 | Michael Brasher | Second Draft |
1.2 | 2006-12-19 | Michael Brasher | Incorporated changes suggested by Robert, John, and Keith. |
1.3 | 2006-12-20 | Michael Brasher | Incorporated comments from PEP review (Robert, John, Keith, Karl, Mike). |
1.4 | 2007-1-11 | Michael Brasher / Karl Schopmeyer | Update with outstanding comments from previous review and definition of session key function requested by HP |
1.5 | 2007-1-17 | Michael Brasher / Karl Schopmeyer | Incorporate comments from 1.4. Note that we are showing the color codes from the previous version (1.4) but have incorporated the changes that were color coded in 1.4 into normal text. |
1.6 | 2007-1-23 | Michael Brasher / Karl Schopmeyer | Comments from Review of 1.5. Approved version. |
1.7 | 2007-5-11 | Roger Kumpf | Rework from discussion and code review by Roger Kumpf
and Mike Brasher. Specifically, these changes are made:
Approved version. |
1.8 | 2007-8-13 | Roger Kumpf | Updated for Bugs 6689, 6704, and 6771:
Approved version. |
Abstract: This PEP describes the inclusion of privilege separation into the OpenPegasus server. Privilege separation aims to substantially reduce the amount of server code running with elevated privilege. This improves server security by limiting vulnerability to a family of client attacks, aimed at exploiting programming errors in order to perform unauthorized privileged operations. The best known example of this kind of attack is the buffer overrun attack [1]. The potential for this kind of attack can be limited by reducing the volume of code that executes with elevated privilege.
A typical privilege separation implementation relocates all privileged code from a server into a separate executor process. Then the executor runs with elevated privilege whereas the server runs with reduced privilege. The executor carries out a limited set of privileged operations on behalf of the server. The executor defines a policy that restricts the allowable parameters to these privileged operations. Without a policy, programming errors in the server might be exploited to trick the executor into performing a privileged operation on an unauthorized object (e.g., the server might ask the executor to execute a rogue program). The executor, server, and policy are depicted in the diagram below.
[executor] <--(requests)-- [server]
^
|
[policy]
In the current Pegasus implementation, all Pegasus server code executes with elevated privilege, which makes the server vulnerable to security attacks aimed at exploiting programming errors in order to execute unauthorized privileged operations. The costs of identifying and fixing these flaws are prohibitive since all server source code must be audited.
+-------------------+ +----------------------+ +-------------------------+The policy definition restricts the parameters permitted for each of the operations.
| policy definition |---- reads --->| executor (cimserver) |<---- socket -----| server (cimservermain) |
+-------------------+ +----------------------+ +-------------------------+
owner=root user=root user=non-root
Note that while the diagram above shows the policy definition in a file, in this
implementation it will be statically compiled into the executor program.
The executor supports the following operations:
Operation | Description |
startProviderAgent | Run the out-of-process provider agent (cimprovagt) as the given user with the given mode. Return a pipe descriptor for communicating with the cimprovagt. |
authenticatePassword | Validate the password for a
given user with the "underlying authentication facilities". This
function will use one of three underlying authentication facilities:
|
validateUser | Verify that a username is valid per the underlying authentication facility (the same facilities specified in the authenticatePassword operation). |
challengeLocal | Initiate a local authentication sequence. Creates a file only readable by the authenticating user and places a randomly generated key in that file. Produces a challenge (containing the path of the file). This challenge is sent back to the authenticating client, which must produce a response. |
authenticateLocal | Finalizes the local authentication sequence initiated by challengeLocal by passing in the response to the challenge. |
daemonizeExecutor | Tell the executor to run as a daemon (in the "background"), that is sever ties with the terminal device, stdio, stderr, and stdout, and fork once more. |
openFile | Opens a file owned by root for read access. Returns a file descriptor for accessing this file. Note that this was originally added so that the control providers could read system information files (containing the information they provider) but it may turn out that it is not needed since all files examined so far are readable by all users. This operation is subject to policy constraints. |
renameFile | Renames the given file. This operation is subject to policy constraints. |
removeFile | Removes the given file. This operation is subject to policy constraints. |
ping | Checks to see if the executor is "alive" (one of the first operations performed by the server process). |
Details about the input and output parameters for each of these operations can be found in the pegasus/src/Executor/Messages.h file
The executor will be written from scratch, since using any of the existing Pegasus libraries would unnecessarily widen the scope of source-level security audits. In other words, the executor implementation will be self contained and will not include any existing Pegasus headers nor will it link any existing Pegasus libraries. Further, the entire executor implementation will be contained in a single source code directory.
Policies will define restrictions on the parameters of
the supported operations. In general a policy consists of the operation
name followed by parameter restrictions. For example, these entries allow
the Pegasus configuration files to be opened for writing:
OpenFile("/pegasus_home/cimserver_current.conf", "w")
OpenFile("/pegasus_home/cimserver_planned.conf", "w")
Similarly, this policy allows any file in the /tmp directory to be removed:
RemoveFile("/tmp/*")
If a policy statement cannot be located for a given request, then the request is rejected.
Policy definitions are statically compiled into the executor and cannot be configured at runtime.
If privilege separation is not enabled, the server will operate without using the calls to the Executor to perform root privilege functions. The external behavior is unchanged in this case.
The
following table defines file ownership and server user access
privileges. The executor may override the access privileges (based on
policy definitions) by opening
the file on behalf of the server and passing back a descriptor.
File | Owner | Writable by server user? | Readable by server user? | Executor actions |
Configuration files (cimserver_current.conf and cimserver_planned.conf) |
root |
no | yes | The executor opens these files for write on behalf of the server. |
CIM Server trace file (cimserver.trc) | server user (Note that individual trace files are used for each cimprovagt, and their owners and permissions are unchanged by this feature) | yes | yes | None |
PID file (cimserver_start.conf) | server user | yes | yes | None |
Start-up lock file (cimserver_start.lock) | server user | yes | yes | None |
Message catalogues |
root |
no | yes | None |
The CIM repository |
server user (cimmofl automatically creates the repository files with the owner set to the server user with privilege separation enabled; installation and upgrade scripts must ensure the correct ownership of these files.) |
yes | yes | None |
Local domain socket node file | server user | yes | yes | None |
Programs | root | no | yes | None |
Pegasus and provider libraries |
root |
no | yes | None |
SSL public certificates |
root |
no | yes | None |
SSL private key | root | no | no | Executor opens the file for read on behalf of the server. |
SSL trust store and CRL store | root | no | yes | Executor opens these files for write on behalf of the server |
Local authentication directory | root | no | yes | Executor creates local authentication files to be read by clients. The CIM Server does not use this directory. |
Pegasus password file (if used) | root | no | no | Executor opens the file for write on behalf of the server. |
In the CIM Server itself, the following source files will contain the bulk of the changes. Minor changes are expected in a few others.
These environment variable definitions will be proposed for PEP 292 (Recommended OpenPegasus 2.7.0 Build and Configuration Options for Selected Platforms):
The behavior of Pegasus is unchanged when privilege separation is
not built. That is:
These questions were considered during the design process. The resolutions are given after each question.
Operation | Description |
startProviderAgent | This existing operation has additional requirements: If the provider UserContext is Requestor, then authentication credentials of the requestor must be passed so that they may be authenticated. Otherwise, the provider UserContext setting is compared with the authentication credentials to validate that the provider may be started in the requested context. |
authenticatePassword | This existing operation must be extended to generate a new session key when authentication is successful. |
challengeLocal | This existing operation must be extended to generate a new session key marked as "unauthenticated". |
authenticateLocal | This existing operation must be extended to validate the session key when authentication is successful. |
newSessionKey (new) | Generates a new session key. This operation is needed by the SSL peer authentication scheme, which will continue to reside entirely in the server process for now. It is also needed to handle the cases of indication provider start-up during initialization and CIMOMHandle calls by in-process providers, since these are not performed on the behalf of an authenticated client. |
deleteSessionKey (new) | Deletes a session key. When connections are closed, session keys are deleted. |
Static policies are compiled into the executor and cannot change. Dynamic policies can be specified at runtime. Dynamic policies are stored in a file (cimserver_policy.conf) owned by root and writable only by root. The policies used by startProviderAgent to define provider access are the only policies that are dynamic. These dynamic policies are intended to encapsulate the provider user context definitions in the provider registration, so that the CIM Server cannot request a provider to be started in a user context that is not intended.
It may seem that provider user context configuration could be retrieved directly from the provider registration information in the repository instead of maintaining a separate but parallel policy file. However, the executor cannot trust the repository since it can be written by the server user. Also, it is technically infeasible for the executor to access the repository because that program is prohibited from linking with Pegasus libraries (for code auditing purposes).
Therefore, a mechanism is needed to keep the dynamic policy definition consistent with the provider registration information. Some options are:
Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM
Corp.;
EMC Corporation; Symantec Corporation; The Open
Group.
Permission is hereby granted, free of charge, to any person
obtaining a copy
of this software and associated documentation files (the
"Software"), to
deal in the Software without restriction, including without
limitation the
rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or
sell copies of the Software, and to permit persons to whom
the Software is
furnished to do so, subject to the following
conditions:
THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL
BE INCLUDED IN
ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE
SOFTWARE IS PROVIDED
"AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.