Securing Kernel and Communication Objects
The preceding sections were concerned mostly with file security, and the same techniques apply to other filelike objects, such as named pipes (Chapter 11), and to kernel objects. Program 15-6, the next example, deals with named pipes, which can be treated in much the same way as files were treated.
Securing Named Pipes
While the code is omitted in the listing of Program 11-3, the server (whose full code appears on the book's Web site) optionally secures its named pipe to prevent access by unauthorized clients. Optional command line parameters specify the user and group name.
Server [UserName GroupName]
If the user and group names are omitted, default security is used. Note that the full version of Program 11-3 (on the Web site) and Program 15-3 to create the optional security attributes. However, rather than calling InitUnixSA, we now use a simpler function, InitializeAccessOnlySA, which only creates access allowed ACEs and puts a final access denied ACE at the end of the ACL. Program 11-3. The important security rights for named pipes are as follows:
Alternatively, simply use STANDARD_RIGHTS_REQUIRED, where all rights are required if the client is to connect. You also need to mask in 0x1FF to obtain full access (duplex, inbound, outbound, and so on). The server in Program 15-6 optionally secures its named pipe instances using these rights. Only clients executed by the owner have access, although it would be straightforward to allow group members to access the pipe as well.
Program 15-6. ServerNP: Securing a Named Pipe
/* Chapter 15. ServerNP. With named pipe security.
* Multithreaded command line server. Named pipe version.
* Usage: Server [UserName GroupName]. */
. . .
_tmain (int argc, LPTSTR argv [])
{
. . .
HANDLE hNp, hMonitor, hSrvrThread [MAX_CLIENTS];
DWORD iNp, MonitorId, ThreadId;
DWORD AceMasks [] = /* Named pipe access rights */
{STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0X1FF, 0, 0 };
LPSECURITY_ATTRIBUTES pNPSA = NULL;
. . .
if (argc == 4) /* Optional pipe security. */
pNPSA = InitializeAccessOnlySA (0440, argv [1], argv [2],
AceMasks, &hSecHeap);
. . .
/* Create a pipe instance for every server thread. */
. . .
for (iNp = 0; iNp < MAX_CLIENTS; iNp++) {
hNp = CreateNamedPipe (SERVER_PIPE, PIPE_ACCESS_DUPLEX,
PIPE_READMODE_MESSAGE | PIPE_TYPE_MESSAGE | PIPE_WAIT,
MAX_CLIENTS, 0, 0, INFINITE, pNPSA);
if (hNp == INVALID_HANDLE_VALUE)
ReportError (_T ("Failure to open named pipe."), 1, TRUE);
. . .
}
Kernel and Private Object Security
Many objects, such as processes, threads, and mutexes, are kernel objects. To get and set kernel security descriptors, use GetKernelObjectSecurity and SetKernelObjectSecurity, which are similar to the file security functions described in this chapter. However, you need to know the access rights appropriate to an object; the next subsection shows how to find the rights.It is also possible to associate security descriptors with private, programmer-generated objects, such as Windows Sockets or a proprietary database. The appropriate functions are GetPrivateObjectSecurity and SetPrivateObjectSecurity. The programmer must take responsibility for enforcing access and must exchange security descriptors with CreatePrivateObjectSecurity and DestroyPrivateObjectSecurity.
ACE Mask Values
The "user, group, everyone" model that InitUnixSA implements will be adequate in many cases, although different models can be implemented using the same basic techniques.It is necessary, however, to determine the actual ACE mask values appropriate for a particular kernel object. The values are not always well documented, but they can be found in several ways.
- Read the documentation for the open call for the object in question. The access flags are the same as the flags used in the ACE mask. For example, OpenMutex uses MUTEX_ALL_ACCESS and SYNCHRONIZE (the second flag is required for any object that can be used with WaitForSingleObject or WaitForMultipleObjects). Other objects, such as processes, have many additional access flags.
- The "create" documentation may also supply useful information.
- Inspect the header files WINNT.H and WINBASE.H for flags that apply to the object.
