Add write access for 'everyone' to named pipe ACL

I have a named pipe server running in a win32 service. I can write to it fine as an admin, but when I logon to Windows as a normal user, I cannot. Based on a quick glance at the docs, this is because the default ACL on named pipes is Everyone = Read, LocalSystem/Admins = Full Control (I'm using NULL as the security descriptor right now).

So, I need to update the ACL on the named pipe to grant Everyone the ability to connect and write, as well as the default read. The security functions look pretty involved... I was hoping someone already has sample code to add the permission.
LVL 4
jimstarAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
jkrConnect With a Mentor Commented:
To create a 'SECURITY_ATTRIBUTES' struct to use with 'CreateNamedPipe()', use
PSID                        psidWorldSid    =   NULL;
SECURITY_DESCRIPTOR         sd;
SECURITY_ATTRIBUTES         sa;
 
 
    //  Create a security descriptor for the log file that allows
    //  access from both the privileged service and the non-privileged
    //  user mode programs
 
    psidWorldSid    =   ( PSID) LocalAlloc  (   LPTR,
                                                GetSidLengthRequired    (   1)
                                            );
 
    InitializeSid   (   psidWorldSid,   &siaWorldSidAuthority,  1);
 
    *(  GetSidSubAuthority  (   psidWorldSid,   0)) =   SECURITY_WORLD_RID;
 
    InitializeSecurityDescriptor    (   &sd,    SECURITY_DESCRIPTOR_REVISION);
 
    SetSecurityDescriptorGroup      (   &sd,    psidWorldSid,   TRUE);
 
    ZeroMemory  (   &sa,    sizeof  (   SECURITY_ATTRIBUTES));
 
    sa.nLength              =   sizeof  (   SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor =   &sd;
    sa.bInheritHandle           =   FALSE;

Open in new window

0
 
jkrCommented:
Sorry, to illustrate that:
HANDLE hPipe = CreateNamedPipeA("\\\\.\\pipe\\MyPipe",PIPE_ACCESS_DUPLEX,PIPE_READMODE_BYTE,PIPE_UNLIMITED_INSTANCES, 8192,8192,NMPWAIT_USE_DEFAULT_WAIT,&sa);

Open in new window

0
 
jimstarAuthor Commented:
>> error C2065: 'siaWorldSidAuthority' : undeclared identifier

I can declare it, but how would I go about initializing this?
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
jkrCommented:
Sorry, one line was missing:


SID_IDENTIFIER_AUTHORITY siaWorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;

Open in new window

0
 
jimstarAuthor Commented:
Works great, thanks. I probably should learn this LSA/sid/acl stuff... the usage is very confusing at first, but likely worth digging into for my long term sanity. So far I've been able to avoid it though. :)
0
 
jimstarAuthor Commented:
I guess I spoke too soon. Still having issues connecting/writing to the named pipe from non-admin interactive sessions. Working on debugging the issue, but something that would help is if you could explain how the above code assigns read/write permission to Everyone (I assume World=Everyone, rather than World=Anonymous).

I see the SID/RID, but not the actual permissions being set. I must be missing something.

Thanks.
0
 
jkrCommented:
Take a look at an alternative approach at http://msdn2.microsoft.com/en-us/library/aa446595.aspx ("Creating a Security Descriptor for a New Object in C++")
#include <windows.h>
#include <stdio.h>
#include <aclapi.h>
 
void main()
{
 
    DWORD dwRes, dwDisposition;
    PSID pEveryoneSID = NULL, pAdminSID = NULL;
    PACL pACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea[2];
    SID_IDENTIFIER_AUTHORITY SIDAuthWorld =
            SECURITY_WORLD_SID_AUTHORITY;
    SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
    SECURITY_ATTRIBUTES sa;
    LONG lRes;
    HKEY hkSub = NULL;
 
    // Create a well-known SID for the Everyone group.
    if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,
                     SECURITY_WORLD_RID,
                     0, 0, 0, 0, 0, 0, 0,
                     &pEveryoneSID))
    {
        printf("AllocateAndInitializeSid Error %u\n", GetLastError());
        goto Cleanup;
    }
 
    // Initialize an EXPLICIT_ACCESS structure for an ACE.
    // The ACE will allow Everyone read access to the key.
    ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS));
    ea[0].grfAccessPermissions = KEY_READ;
    ea[0].grfAccessMode = SET_ACCESS;
    ea[0].grfInheritance= NO_INHERITANCE;
    ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea[0].Trustee.ptstrName  = (LPTSTR) pEveryoneSID;
 
    // Create a SID for the BUILTIN\Administrators group.
    if(! AllocateAndInitializeSid(&SIDAuthNT, 2,
                     SECURITY_BUILTIN_DOMAIN_RID,
                     DOMAIN_ALIAS_RID_ADMINS,
                     0, 0, 0, 0, 0, 0,
                     &pAdminSID)) 
    {
        printf("AllocateAndInitializeSid Error %u\n", GetLastError());
        goto Cleanup; 
    }
 
    // Initialize an EXPLICIT_ACCESS structure for an ACE.
    // The ACE will allow the Administrators group full access to
    // the key.
    ea[1].grfAccessPermissions = KEY_ALL_ACCESS;
    ea[1].grfAccessMode = SET_ACCESS;
    ea[1].grfInheritance= NO_INHERITANCE;
    ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
    ea[1].Trustee.ptstrName  = (LPTSTR) pAdminSID;
 
    // Create a new ACL that contains the new ACEs.
    dwRes = SetEntriesInAcl(2, ea, NULL, &pACL);
    if (ERROR_SUCCESS != dwRes) 
    {
        printf("SetEntriesInAcl Error %u\n", GetLastError());
        goto Cleanup;
    }
 
    // Initialize a security descriptor.  
    pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, 
                             SECURITY_DESCRIPTOR_MIN_LENGTH); 
    if (NULL == pSD) 
    { 
        printf("LocalAlloc Error %u\n", GetLastError());
        goto Cleanup; 
    } 
 
    if (!InitializeSecurityDescriptor(pSD,
            SECURITY_DESCRIPTOR_REVISION)) 
    {  
        printf("InitializeSecurityDescriptor Error %u\n",
                                GetLastError());
        goto Cleanup; 
    } 
 
    // Add the ACL to the security descriptor. 
    if (!SetSecurityDescriptorDacl(pSD, 
            TRUE,     // bDaclPresent flag   
            pACL, 
            FALSE))   // not a default DACL 
    {  
        printf("SetSecurityDescriptorDacl Error %u\n",
                GetLastError());
        goto Cleanup; 
    } 
 
    // Initialize a security attributes structure.
    sa.nLength = sizeof (SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = pSD;
    sa.bInheritHandle = FALSE;
 
    // Use the security attributes to set the security descriptor 
    // when you create a key.
    lRes = RegCreateKeyEx(HKEY_CURRENT_USER, "mykey", 0, "", 0, 
            KEY_READ | KEY_WRITE, &sa, &hkSub, &dwDisposition); 
    printf("RegCreateKeyEx result %u\n", lRes );
 
Cleanup:
 
    if (pEveryoneSID) 
        FreeSid(pEveryoneSID);
    if (pAdminSID) 
        FreeSid(pAdminSID);
    if (pACL) 
        LocalFree(pACL);
    if (pSD) 
        LocalFree(pSD);
    if (hkSub) 
        RegCloseKey(hkSub);
 
    return;
 
}

Open in new window

0
 
jimstarAuthor Commented:
I've built up a function to adjust the security descriptor, using the information in the various articles on MSDN. However, when I try to query the existing security descriptor and DACL from my named pipe, it failes with ERROR_INVALID_PARAMETER (87L).

BOOL AdjustPipeDACL(HANDLE hPipe)
{
      //
      // Obtain the existing DACL
      //

      PACL pExistingAcl = NULL;                        // ACL pointer
      PSECURITY_DESCRIPTOR pSD = NULL;            // SD pointer
      DWORD dwResult = 0;

      dwResult = GetSecurityInfo(
            hPipe,                                                // Handle to the pipe
            SE_FILE_OBJECT,                                    // Named pipe is a file object
            DACL_SECURITY_INFORMATION,                  // Request the DACL of the object
            0,                                                      // Don't need the owner info
            0,                                                      // Don't need the group info
            &pExistingAcl,                                    // Receives a pointer to the existing ACL
            0,                                                      // Don't need the SACL info
            &pSD);                                                // Security descriptor
      
      if(dwResult != ERROR_SUCCESS)
      {
            // An error occurred getting security info
            return FALSE;
      }
...

For some reason, I keep getting dwResult == 87L. The handle passed in appears to be valid from a newly created pipe. The pipe was created with a default security descriptor. Any ideas what might be going wrong?
0
 
jimstarAuthor Commented:
BTW, this is where the pipe is created.

      for(;;)
      {
            HANDLE hNamedPipe = CreateNamedPipe(CONFIG_PIPENAME,      // Name of pipe
                        PIPE_ACCESS_DUPLEX,            // Inbound and outbound access
                        PIPE_TYPE_MESSAGE            // Attributes of the pipe
                         | PIPE_READMODE_MESSAGE
                        | PIPE_WAIT,
                        PIPE_UNLIMITED_INSTANCES,      // the more the better
                        5*sizeof(CONFIG_MESSAGE),// Out buffer size
                        5*sizeof(CONFIG_MESSAGE),// In buffer size
                        0,                                    // Default timeout value
                        NULL);                              // Don't inherit security attributes

            if(hNamedPipe == INVALID_HANDLE_VALUE)
            {
                  // An error occurred
                  Sleep(1000);
                  continue;
            }

            // Adjust the permissions so ordinary users can connect
            AdjustPipeDACL(hNamedPipe);
0
 
jkrCommented:
Hm, try SE_KERNEL_OBJECT instead - I have a vague remembrance here...

             
      dwResult = GetSecurityInfo(
            hPipe,                                                // Handle to the pipe
            SE_KERNEL_OBJECT,                                    // Named pipe is a file object
            DACL_SECURITY_INFORMATION,                  // Request the DACL of the object
            0,                                                      // Don't need the owner info
            0,                                                      // Don't need the group info
            &pExistingAcl,                                    // Receives a pointer to the existing ACL
            0,                                                      // Don't need the SACL info
            &pSD);              

Open in new window

0
 
jimstarAuthor Commented:
I think I've got it properly merging the new ACE into the existing ACL (although I can't really test it yet), but now when I try and set the new DACL on the existing security descriptor it gives me an INVALID SECURITY DESCRIPTOR error (#define ERROR_INVALID_SECURITY_DESCR     1338L).

Here's a quick command line app I wrote up to demonstrate the exact issue end-to-end. If this isn't your area, I can post a new Q for others to look at the problem.
#include "stdafx.h"
#include <windows.h>
#include <aclapi.h>
 
// Adjusts the pipe DACL to allow Everyone read/write access
// while leaving default/existing entries in place.
BOOL AdjustPipeDACL(HANDLE hPipe)
{
	//
	// Obtain the existing DACL
	//
 
	PACL pExistingAcl = NULL;		// ACL pointer
	PSECURITY_DESCRIPTOR pSD = NULL;	// SD pointer
	DWORD dwResult = 0;
 
	dwResult = GetSecurityInfo(
		hPipe,				// Handle to the pipe
		SE_KERNEL_OBJECT,		// Named pipe is a file object
		DACL_SECURITY_INFORMATION,	// Request the DACL of the object
		0,				// Don't need the owner info
		0,				// Don't need the group info
		&pExistingAcl,			// Receives a pointer to the existing ACL
		0,				// Don't need the SACL info
		&pSD);				// Security descriptor
	
	if(dwResult != ERROR_SUCCESS)
	{
		// An error occured getting security info
		printf("Error condition 1.\n");
		return FALSE;
	}
 
	//
	// Merge the new entry into the existing DACL
	//
 
	SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
	PSID pEveryoneSID = NULL;
	EXPLICIT_ACCESS ea;
	DWORD dwRes;
	PACL pNewAcl = NULL;
 
    // Create a well-known SID for the Everyone group.
    if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID,
		0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))
    {
		printf("Error condition 2.\n");
		return FALSE;
    }
 
    // Initialize an EXPLICIT_ACCESS structure for an ACE.
    // The ACE will allow Everyone read/write access.
    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    ea.grfAccessPermissions = GENERIC_READ | GENERIC_WRITE;
    ea.grfAccessMode = GRANT_ACCESS;
    ea.grfInheritance= NO_INHERITANCE;
    ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea.Trustee.ptstrName  = (LPTSTR) pEveryoneSID;
 
    // Create a new ACL that contains the new ACEs.
    dwRes = SetEntriesInAcl(1, &ea, pExistingAcl, &pNewAcl);
    if (ERROR_SUCCESS != dwRes) 
    {
		printf("Error condition 3.\n");
		return FALSE;
    }
 
	//
	// Set the DACL on the pipe object to our new ACL
	//
 
	if(!SetSecurityDescriptorDacl(
		pSD,							// Security descriptor to modify
		TRUE,							// DACL present in the descriptor
		pNewAcl,						// Use the provided ACL
		FALSE))							// Explicitly created DACL (not a default)
	{
		DWORD dwErr = GetLastError();
		printf("Error condition 4.\n");
		return FALSE;
	}
 
	//
	// Cleanup
	//
	LocalFree(pSD);
	LocalFree(pExistingAcl);
    if (pEveryoneSID) FreeSid(pEveryoneSID);
 
	return TRUE;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
	for(;;)
	{
		HANDLE hNamedPipe = CreateNamedPipe
			(L"\\\\.\\PIPE\\PIPETEST",	// Name of pipe
			PIPE_ACCESS_DUPLEX,			// Inbound and outbound access
			PIPE_TYPE_MESSAGE			// Attributes of the pipe
			| PIPE_READMODE_MESSAGE
			| PIPE_WAIT,
			PIPE_UNLIMITED_INSTANCES,	// the more the better
			512,						// Out buffer size
			512,						// In buffer size
			0,							// Default timeout value
			NULL);						// Don't inherit security attributes
 
		if(hNamedPipe == INVALID_HANDLE_VALUE)
		{
			printf("An error occured creating the named pipe.\n");
			Sleep(1000);
			continue;
		}
 
		// Adjust the permissions so ordinary users can connect
		if(!AdjustPipeDACL(hNamedPipe))
			break;
 
		// Wait for a client to be connected
		printf("Waiting for a client to connect...\n");
		ConnectNamedPipe(hNamedPipe, NULL);
 
		// Close the handle and move on, since we're just testing
		CloseHandle(hNamedPipe);
		continue;
 
	}
 
	getchar();
	return 0;
}

Open in new window

0
 
jimstarAuthor Commented:
dwErr on line 80 above (Error Condition 4) is the one that fails with the invalid security descriptor last error.
0
 
jkrCommented:
Hm, at first glance, that seems OK. I have to leave the office now, but promise to take a look again later - which might be in 15mins, yet can be later. Need to give my cold a short cure :-(
0
 
jimstarAuthor Commented:
No rush, thanks for the help!
0
 
jkrCommented:
Could you try the following?
BOOL AdjustPipeDACL(HANDLE hPipe)
{
	//
	// Obtain the existing DACL
	//
 
	PACL pExistingAcl = NULL;		// ACL pointer
	PSECURITY_DESCRIPTOR pSD = NULL;	// SD pointer
	DWORD dwResult = 0;
 
	dwResult = GetSecurityInfo(
		hPipe,				// Handle to the pipe
		SE_KERNEL_OBJECT,		// Named pipe is a file object
		DACL_SECURITY_INFORMATION,	// Request the DACL of the object
		0,				// Don't need the owner info
		0,				// Don't need the group info
		&pExistingAcl,			// Receives a pointer to the existing ACL
		0,				// Don't need the SACL info
		&pSD);				// Security descriptor
 
	
	if(dwResult != ERROR_SUCCESS)
	{
		// An error occured getting security info
		printf("Error condition 1.\n");
		return FALSE;
	}
 
	//
	// Merge the new entry into the existing DACL
	//
 
	SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
	PSID pEveryoneSID = NULL;
	EXPLICIT_ACCESS ea;
	DWORD dwRes;
	PACL pNewAcl = NULL;
 
    LPTSTR TrusteeName = L".\\Everyone";
 
    BuildExplicitAccessWithName(
        &ea,
        TrusteeName,
        GENERIC_READ | GENERIC_WRITE | STANDARD_RIGHTS_READ | STANDARD_RIGHTS_WRITE,
        SET_ACCESS,
        0
        );
 
    // Create a new ACL that contains the new ACEs.
    dwRes = SetEntriesInAcl(1, &ea, pExistingAcl, &pNewAcl);
    if (ERROR_SUCCESS != dwRes) 
    {
		printf("Error condition 3: %d\n", dwRes);
		return FALSE;
    }
 
	//
	// Set the DACL on the pipe object to our new ACL
	//
 
	if(!SetSecurityDescriptorDacl(
		pSD,							// Security descriptor to modify
		TRUE,							// DACL present in the descriptor
		pNewAcl,						// Use the provided ACL
		FALSE))							// Explicitly created DACL (not a default)
	{
		DWORD dwErr = GetLastError();
		printf("Error condition 4: %d\n",dwErr);
		return FALSE;
	}
 
	//
	// Cleanup
	//
	LocalFree(pSD);
	LocalFree(pExistingAcl);
    if (pEveryoneSID) FreeSid(pEveryoneSID);
 
	return TRUE;
}

Open in new window

0
 
jimstarAuthor Commented:
Error condition 3 - 1332

#define ERROR_NONE_MAPPED                1332L
// MessageText:
//  No mapping between account names and security IDs was done
0
 
jkrCommented:
Sh*t - yet I had to ask, since my Windows is localized and uses different group names (which I couldn't figure out quickly).

BTW, why do you want to keep the other access rights in the ACL, since "Everyone" being granted access effectively nullifies their impact?
0
 
jimstarAuthor Commented:
I thought it'd be a cleaner solution to simply add the needed permissions, instead of clear out any default perms that already exist. (doesn't SYSTEM or the creator have special access to write the DACL, delete the object, etc etc?). Anyway, rather than try to figure out exactly what I needed to re-add to ensure that my SYSTEM service had the right permissions to manage the pipe, I thought I'd just add Everyone to the ACL. I'm really not that knowledgeable about the permissions I'd need to grant if I created a *brand new* ACL from scratch. By adding to the existing one, I let the system deal with that. :)

And, as I worked on my code, I started to wonder why it wasn't working, given the relative short amount of code it takes to do what I think I want to do. That's why I kept pursuing it from that angle. But maybe it's easier to just create a new one...
0
 
jkrCommented:
>>I thought it'd be a cleaner solution to simply add the needed permissions

If you add "Everyone", that does not make a difference, yet if you need a better granularity (e.g. adding the group of "SuperDuperPipeUsers"), I'd also try to go that way. I am also curious what the problem is, yet that has to wait until tomorrow now ;o)

(the cold takes it's toll)
0
 
jkrCommented:
Hm, got it. At least, I am quite sure that this is what it boils down to: http://msdn2.microsoft.com/en-us/library/aa379583.aspx ("SetSecurityDescriptorDacl")

pSecurityDescriptor
A pointer to the SECURITY_DESCRIPTOR structure to which the function adds the DACL. This security descriptor must be in *absolute format*, meaning that its members must be pointers to other structures, rather than offsets to contiguous data.

See also http://msdn2.microsoft.com/en-us/library/aa374807.aspx ("Absolute and Self-Relative Security Descriptors")
0
 
jimstarAuthor Commented:
I'll have to check the actual SD when I get it from GetSecurityInfo. When I read about the absolute/relative last night, it said that self-relative SDs were usually used for storing an SD to floppy or similar, and that most uses were absolute. So I figured that Windows must be giving me an absolute. But I'll check it out later today and let you know what I discover.
0
 
jkrCommented:
Well, it works with an absolute SD, I've tried it ;o)

PS: Wenn it rains, it pours - my emails are 1h late, just checked here accidentially :-(
0
 
jkrCommented:
Ooops, I forgot the code - no, actually, I was hoping, you'd make that a new Q ;o)
#define UNICODE
#include <windows.h>
#include <aclapi.h>
#include <stdio.h>
#include <tchar.h>
 
#pragma comment(lib,"advapi32.lib")
 
BOOL MakeSDAbsolute(PSID pSD, PSID* ppAbs)
{
 
VOID    *pAbsoluteSD = NULL; 
DWORD   AbsoluteSDSize = 0;
VOID    *pDacl = NULL;
DWORD   DaclSize = 0;
VOID    *pSacl = NULL;
DWORD   SaclSize = 0;
VOID    *pOwner = NULL;
DWORD   OwnerSize = 0;
VOID    *pGroup = NULL;
DWORD   GroupSize = 0;
 
 
    if( ! MakeAbsoluteSD(
                      pSD,
                      (PSECURITY_DESCRIPTOR)pAbsoluteSD,
                      &AbsoluteSDSize,
                      (PACL)pDacl,
                      &DaclSize,
                      (PACL)pSacl,
                      &SaclSize,
                      (PSID)pOwner,
                      &OwnerSize,
                      (PSID)pGroup,
                      &GroupSize
                      ))
    {
        pAbsoluteSD = 
           (PSECURITY_DESCRIPTOR)LocalAlloc(0,AbsoluteSDSize);
        if(!pAbsoluteSD)
        {
            // TODO: handle this.
        }
        pDacl = (PACL)LocalAlloc(0,DaclSize);
        if(!pDacl)
        {
            // TODO: handle this.
        }
        pSacl = (PACL)LocalAlloc(0,SaclSize);
        if(!pSacl)
        {
            // TODO: handle this.
        }
        pOwner = (PSID)LocalAlloc(0,OwnerSize);
        if(!pOwner)
        {
            // TODO: handle this.
        }
        pGroup = (PSID)LocalAlloc(0,GroupSize);
        if(!pGroup)
        {
            // TODO: handle this.
        }
        if( ! MakeAbsoluteSD(
                          pSD,
                          (PSECURITY_DESCRIPTOR)pAbsoluteSD,
                          &AbsoluteSDSize,
                          (PACL)pDacl,
                          &DaclSize,
                          (PACL)pSacl,
                          &SaclSize,
                          (PSID)pOwner,
                          &OwnerSize,
                          (PSID)pGroup,
                          &GroupSize
                  ))
        {
            //
            // TODO: handle this.
            //
            // Cleanup and return.
            
            return FALSE;
 
        }
 
    }
 
    *ppAbs = pAbsoluteSD;
 
    LocalFree(pDacl);
    LocalFree(pSacl);
    LocalFree(pGroup);
    LocalFree(pOwner);
 
    return TRUE;
 
}
 
// Adjusts the pipe DACL to allow Everyone read/write access
// while leaving default/existing entries in place.
BOOL AdjustPipeDACL(HANDLE hPipe)
{
	//
	// Obtain the existing DACL
	//
 
	PACL pExistingAcl = NULL;		// ACL pointer
	PSECURITY_DESCRIPTOR pSD = NULL;	// SD pointer
	DWORD dwResult = 0;
 
	dwResult = GetSecurityInfo(
		hPipe,				// Handle to the pipe
		SE_KERNEL_OBJECT,		// Named pipe is a file object
		DACL_SECURITY_INFORMATION,	// Request the DACL of the object
		0,				// Don't need the owner info
		0,				// Don't need the group info
		&pExistingAcl,			// Receives a pointer to the existing ACL
		0,				// Don't need the SACL info
		&pSD);				// Security descriptor
 
        printf("pSD: 0x%8.8x\n", pSD);
	
        if (!IsValidSecurityDescriptor(pSD))
        {
		printf("Invalid PSECURITY_DESCRIPTOR\n");
		return FALSE;
        }
	if(dwResult != ERROR_SUCCESS)
	{
		// An error occured getting security info
		printf("Error condition 1.\n");
		return FALSE;
	}
 
	//
	// Merge the new entry into the existing DACL
	//
 
	SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
	PSID pEveryoneSID = NULL;
	EXPLICIT_ACCESS ea;
	DWORD dwRes;
	PACL pNewAcl = NULL;
 
    // Create a well-known SID for the Everyone group.
    if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID,
		0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))
    {
		printf("Error condition 2.\n");
		return FALSE;
    }
 
    // Initialize an EXPLICIT_ACCESS structure for an ACE.
    // The ACE will allow Everyone read/write access.
    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    ea.grfAccessPermissions = GENERIC_READ | GENERIC_WRITE;
    ea.grfAccessMode = GRANT_ACCESS;
    ea.grfInheritance= NO_INHERITANCE;
    ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea.Trustee.ptstrName  = (LPTSTR) pEveryoneSID;
 
    // Create a new ACL that contains the new ACEs.
    dwRes = SetEntriesInAcl(1, &ea, pExistingAcl, &pNewAcl);
    if (ERROR_SUCCESS != dwRes) 
    {
		printf("Error condition 3.\n");
		return FALSE;
    }
 
    if (!IsValidAcl(pNewAcl))
     {
		printf("Invalid ACL\n");
		return FALSE;
    }
 
    PSECURITY_DESCRIPTOR pAbsolute = NULL;
 
    if (!MakeSDAbsolute(pSD,&pAbsolute))
     {
		printf("'Absoluting' failed\n");
		return FALSE;
    }
	//
	// Set the DACL on the pipe object to our new ACL
	//
 
	if(!SetSecurityDescriptorDacl(
		pAbsolute,							// Security descriptor to modify
		TRUE,							// DACL present in the descriptor
		pNewAcl,						// Use the provided ACL
		FALSE))							// Explicitly created DACL (not a default)
	{
		DWORD dwErr = GetLastError();
		printf("Error condition 4. %d\n",dwErr);
		return FALSE;
	}
 
	//
	// Cleanup
	//
	LocalFree(pSD);
	LocalFree(pExistingAcl);
    if (pEveryoneSID) FreeSid(pEveryoneSID);
 
	return TRUE;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
	for(;;)
	{
		HANDLE hNamedPipe = CreateNamedPipe
			(L"\\\\.\\PIPE\\PIPETEST",	// Name of pipe
			PIPE_ACCESS_DUPLEX,			// Inbound and outbound access
			PIPE_TYPE_MESSAGE			// Attributes of the pipe
			| PIPE_READMODE_MESSAGE
			| PIPE_WAIT,
			PIPE_UNLIMITED_INSTANCES,	// the more the better
			512,						// Out buffer size
			512,						// In buffer size
			0,							// Default timeout value
			NULL);						// Don't inherit security attributes
 
		if(hNamedPipe == INVALID_HANDLE_VALUE)
		{
			printf("An error occured creating the named pipe.\n");
			Sleep(1000);
			continue;
		}
 
		// Adjust the permissions so ordinary users can connect
		if(!AdjustPipeDACL(hNamedPipe))
			break;
 
		// Wait for a client to be connected
		printf("Waiting for a client to connect...\n");
		ConnectNamedPipe(hNamedPipe, NULL);
 
		// Close the handle and move on, since we're just testing
		CloseHandle(hNamedPipe);
		continue;
 
	}
 
	getchar();
	return 0;
}

Open in new window

0
 
jimstarAuthor Commented:
Wow, that was going to be my project later tonight... it'll still have to wait until later tonight, but this will definitely make it go quicker. :)
0
 
jkrCommented:
Well, I definitely get a "Waiting for a client to connect..."
0
 
jimstarAuthor Commented:
Hm... still ERROR_ACCESS_DENIED from the connection call. I'll keep playing around with it.
	// Attempt to connect to the server
	HANDLE hNamedPipe = CreateFile(CONFIG_PIPENAME,		// Name of pipe
									GENERIC_WRITE|
									GENERIC_READ,	// Permission
									0,				// No sharing
									NULL,			// Default security descriptors
									OPEN_EXISTING,	// Existing named pipe
									0,				// Default attributes
									NULL);			// No template file

Open in new window

0
 
jimstarAuthor Commented:
It bothers me that I don't understand why this isn't working... but for now I'll just provide a new SD when I create the pipe. That works fine.

By the way, do you know what permissions I need to grant? I can grant Everyone GENERIC_READ|GENERIC_WRITE, but don't I have to grant SYSTEM and Administrators WRITE_DACL and other permissions? Otherwise providing a single EA entry with Everyone read/write would lock my service out of managing the pipe, right?
0
 
jkrCommented:
Hm, does that work if you replace the SD? I am curious, sice I copied the 1st snippet from production code...
0
All Courses

From novice to tech pro — start learning today.