Article ID: 171273
Article Last Modified on 11/21/2006
/* Secure Server Sample
David Mowers (davemo) 15-May-97 */
#include <windows.h>
#include <stdio.h>
// This code must be linked with the Advapi32.lib file.
// Make up some private access rights.
#define ACCESS_READ 1
#define ACCESS_WRITE 2
void main(int argc, char *argv[]) {
PSECURITY_DESCRIPTOR psdSD;
// User/SID variables.
HANDLE hToken = NULL;
PTOKEN_USER ptuUser = NULL;
DWORD cbBuffer = 0;
PSID pUserSid = NULL;
// ACE variables.
DWORD dwAccessMask = ACCESS_READ | ACCESS_WRITE;
PACL pACL = NULL;
DWORD dwACLSize;
// AccessCheck() variables
DWORD dwAccessDesired;
PRIVILEGE_SET PrivilegeSet;
DWORD dwPrivSetSize;
DWORD dwAccessGranted;
BOOL fAccessGranted = FALSE;
GENERIC_MAPPING GenericMapping;
__try {
// Get a SID for later use. A real server would use a function
// such as LookupAccountName() to get SIDs that you will use to
// build your access control list.
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken)) {
printf("Error %d:OpenProcessToken", GetLastError());
__leave;
}
// Determine required size of buffer for token information.
if (GetTokenInformation(hToken, TokenUser, NULL, 0, &cbBuffer)) {
// Call should have failed due to zero-length buffer.
__leave;
} else {
// Call should have failed due to zero-length buffer.
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
__leave;
}
// Allocate buffer for token information.
ptuUser = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
cbBuffer);
if (!ptuUser)
__leave;
if (!GetTokenInformation(hToken, TokenUser, ptuUser, cbBuffer,
&cbBuffer))
__leave;
pUserSid = ptuUser->User.Sid;
// Build a Security Descriptor.
psdSD = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
SECURITY_DESCRIPTOR_MIN_LENGTH);
if(!InitializeSecurityDescriptor(psdSD,
SECURITY_DESCRIPTOR_REVISION)) {
printf("Error %d:InitializeSecurityDescriptor\n",
GetLastError());
__leave;
}
// Compute size needed for the ACL.
dwACLSize = sizeof(ACCESS_ALLOWED_ACE) + 8 +
GetLengthSid(pUserSid) - sizeof(DWORD);
// Allocate memory for ACL.
pACL = (PACL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
dwACLSize);
// Initialize the new ACL.
if(!InitializeAcl(pACL, dwACLSize, ACL_REVISION2)) {
printf("Error %d:InitializeAcl\n", GetLastError());
__leave;
}
// Add the access-allowed ACE to the DACL.
if(!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask,
pUserSid)) {
printf("Error %d:AddAccessAllowedAce",GetLastError());
__leave;
}
// Set our DACL to the SD.
if (!SetSecurityDescriptorDacl(psdSD, TRUE, pACL, FALSE)) {
printf("Error %d:SetSecurityDescriptorDacl", GetLastError());
__leave;
}
// AccessCheck() is picky about what is in the SD. Set the group
// and owner using our convenient SID.
SetSecurityDescriptorGroup(psdSD, pUserSid, FALSE);
SetSecurityDescriptorOwner(psdSD, pUserSid, FALSE);
// AccessCheck() requires an impersonation token.
// For demonstration purposes, we are going to impersonate
// ourselves. A real server would impersonate the client by using
// ImpersonateNamedPipeClient(), RPCImpersonateClient(),
// ImpersonateLoggedOnUser() with a token obtained through
// LogonUser() or the SSPI API ImpersonateSecurityContext().
ImpersonateSelf(SecurityImpersonation);
OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE,
&hToken);
// Using AccessCheck(), there are two different things we could do:
//
// 1. See if we have Read/Write access to the object.
//
dwAccessDesired = ACCESS_READ;
// Initialize generic mapping structure to map all.
memset(&GenericMapping, 0xff, sizeof(GENERIC_MAPPING));
GenericMapping.GenericRead = ACCESS_READ;
GenericMapping.GenericWrite = ACCESS_WRITE;
GenericMapping.GenericExecute = 0;
GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE;
// This only does something if we want to use generic access
// rights, like GENERIC_ALL, in our call to AccessCheck().
MapGenericMask(&dwAccessDesired, &GenericMapping);
dwPrivSetSize = sizeof(PRIVILEGE_SET);
// Make the AccessCheck() call.
if(!AccessCheck(psdSD, hToken, dwAccessDesired, &GenericMapping,
&PrivilegeSet, &dwPrivSetSize, &dwAccessGranted,
&fAccessGranted)) {
printf("Error in AccessCheck : %lu\n", GetLastError());
__leave;
} else {
if (fAccessGranted)
printf("Access was granted using mask %lx.\n",
dwAccessGranted);
else
printf("Access was NOT granted!\n");
}
//
// 2. Determine the maximum access I am allowed.
//
dwAccessDesired = MAXIMUM_ALLOWED;
if(!AccessCheck(psdSD, hToken, dwAccessDesired, &GenericMapping,
&PrivilegeSet, &dwPrivSetSize, &dwAccessGranted,
&fAccessGranted)) {
printf("Error in AccessCheck : %lu\n", GetLastError());
__leave;
} else {
if (fAccessGranted)
printf("Maximum Access Allowed = %lx\n", dwAccessGranted);
}
RevertToSelf();
} __finally {
// Close handles and free heap allocations.
if (hToken)
CloseHandle(hToken);
if (ptuUser)
HeapFree(GetProcessHeap(), 0, ptuUser);
if (pACL)
HeapFree(GetProcessHeap(), 0, pACL);
if (psdSD)
HeapFree(GetProcessHeap(), 0, psdSD);
}
}
Keywords: kbapi kbcode kbhowto kbkernbase kbprogramming KB171273