home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / dcom / dcomperm / sdmgmt.cpp < prev    next >
C/C++ Source or Header  |  1997-04-07  |  13KB  |  522 lines

  1. /*++
  2.  
  3. DCOM Permission Configuration Sample
  4. Copyright (c) 1996, Microsoft Corporation. All rights reserved.
  5.  
  6. Module Name:
  7.  
  8.     sdmgmt.cpp
  9.  
  10. Abstract:
  11.  
  12.     Routines to manage security descriptors
  13.  
  14. Author:
  15.  
  16.     Michael Nelson
  17.  
  18. Environment:
  19.  
  20.     Windows NT
  21.  
  22. --*/
  23.  
  24. #include <windows.h>
  25. #include <stdio.h>
  26. #include <conio.h>
  27. #include <tchar.h>
  28. #include "ntsecapi.h"
  29. #include "dcomperm.h"
  30.  
  31. DWORD
  32. CreateNewSD (
  33.     SECURITY_DESCRIPTOR **SD
  34.     )
  35. {
  36.     PACL    dacl;
  37.     DWORD   sidLength;
  38.     PSID    sid;
  39.     PSID    groupSID;
  40.     PSID    ownerSID;
  41.     DWORD   returnValue;
  42.  
  43.     *SD = NULL;
  44.  
  45.     returnValue = GetCurrentUserSID (&sid);
  46.     if (returnValue != ERROR_SUCCESS)
  47.         return returnValue;
  48.  
  49.     sidLength = GetLengthSid (sid);
  50.  
  51.     *SD = (SECURITY_DESCRIPTOR *) malloc (
  52.         (sizeof (ACL)+sizeof (ACCESS_ALLOWED_ACE)+sidLength) +
  53.         (2 * sidLength) +
  54.         sizeof (SECURITY_DESCRIPTOR));
  55.  
  56.     groupSID = (SID *) (*SD + 1);
  57.     ownerSID = (SID *) (((BYTE *) groupSID) + sidLength);
  58.     dacl = (ACL *) (((BYTE *) ownerSID) + sidLength);
  59.  
  60.     if (!InitializeSecurityDescriptor (*SD, SECURITY_DESCRIPTOR_REVISION))
  61.     {
  62.         free (*SD);
  63.         free (sid);
  64.         return GetLastError();
  65.     }
  66.  
  67.     if (!InitializeAcl (dacl,
  68.                         sizeof (ACL)+sizeof (ACCESS_ALLOWED_ACE)+sidLength,
  69.                         ACL_REVISION2))
  70.     {
  71.         free (*SD);
  72.         free (sid);
  73.         return GetLastError();
  74.     }
  75.  
  76.     if (!AddAccessAllowedAce (dacl,
  77.                               ACL_REVISION2,
  78.                               COM_RIGHTS_EXECUTE,
  79.                               sid))
  80.     {
  81.         free (*SD);
  82.         free (sid);
  83.         return GetLastError();
  84.     }
  85.  
  86.     if (!SetSecurityDescriptorDacl (*SD, TRUE, dacl, FALSE))
  87.     {
  88.         free (*SD);
  89.         free (sid);
  90.         return GetLastError();
  91.     }
  92.  
  93.     memcpy (groupSID, sid, sidLength);
  94.     if (!SetSecurityDescriptorGroup (*SD, groupSID, FALSE))
  95.     {
  96.         free (*SD);
  97.         free (sid);
  98.         return GetLastError();
  99.     }
  100.  
  101.     memcpy (ownerSID, sid, sidLength);
  102.     if (!SetSecurityDescriptorOwner (*SD, ownerSID, FALSE))
  103.     {
  104.         free (*SD);
  105.         free (sid);
  106.         return GetLastError();
  107.     }
  108.     return ERROR_SUCCESS;
  109. }
  110.  
  111.  
  112. DWORD
  113. MakeSDAbsolute (
  114.     PSECURITY_DESCRIPTOR OldSD,
  115.     PSECURITY_DESCRIPTOR *NewSD
  116.     )
  117. {
  118.     PSECURITY_DESCRIPTOR  sd;
  119.     DWORD                 descriptorSize;
  120.     DWORD                 daclSize;
  121.     DWORD                 saclSize;
  122.     DWORD                 ownerSIDSize;
  123.     DWORD                 groupSIDSize;
  124.     PACL                  dacl;
  125.     PACL                  sacl;
  126.     PSID                  ownerSID;
  127.     PSID                  groupSID;
  128.     BOOL                  present;
  129.     BOOL                  systemDefault;
  130.  
  131.     //
  132.     // Get SACL
  133.     //
  134.  
  135.     if (!GetSecurityDescriptorSacl (OldSD, &present, &sacl, &systemDefault))
  136.         return GetLastError();
  137.  
  138.     if (sacl && present)
  139.     {
  140.         saclSize = sacl->AclSize;
  141.     } else saclSize = 0;
  142.  
  143.     //
  144.     // Get DACL
  145.     //
  146.  
  147.     if (!GetSecurityDescriptorDacl (OldSD, &present, &dacl, &systemDefault))
  148.         return GetLastError();
  149.  
  150.     if (dacl && present)
  151.     {
  152.         daclSize = dacl->AclSize;
  153.     } else daclSize = 0;
  154.  
  155.     //
  156.     // Get Owner
  157.     //
  158.  
  159.     if (!GetSecurityDescriptorOwner (OldSD, &ownerSID, &systemDefault))
  160.         return GetLastError();
  161.  
  162.     ownerSIDSize = GetLengthSid (ownerSID);
  163.  
  164.     //
  165.     // Get Group
  166.     //
  167.  
  168.     if (!GetSecurityDescriptorGroup (OldSD, &groupSID, &systemDefault))
  169.         return GetLastError();
  170.  
  171.     groupSIDSize = GetLengthSid (groupSID);
  172.  
  173.     //
  174.     // Do the conversion
  175.     //
  176.  
  177.     descriptorSize = 0;
  178.  
  179.     MakeAbsoluteSD (OldSD, sd, &descriptorSize, dacl, &daclSize, sacl,
  180.                     &saclSize, ownerSID, &ownerSIDSize, groupSID,
  181.                     &groupSIDSize);
  182.  
  183.     sd = (PSECURITY_DESCRIPTOR) new BYTE [SECURITY_DESCRIPTOR_MIN_LENGTH];
  184.     if (!InitializeSecurityDescriptor (sd, SECURITY_DESCRIPTOR_REVISION))
  185.         return GetLastError();
  186.  
  187.     if (!MakeAbsoluteSD (OldSD, sd, &descriptorSize, dacl, &daclSize, sacl,
  188.                          &saclSize, ownerSID, &ownerSIDSize, groupSID,
  189.                          &groupSIDSize))
  190.         return GetLastError();
  191.  
  192.     *NewSD = sd;
  193.     return ERROR_SUCCESS;
  194. }
  195.  
  196. DWORD
  197. SetNamedValueSD (
  198.     HKEY RootKey,
  199.     LPTSTR KeyName,
  200.     LPTSTR ValueName,
  201.     SECURITY_DESCRIPTOR *SD
  202.     )
  203. {
  204.     DWORD   returnValue;
  205.     DWORD   disposition;
  206.     HKEY    registryKey;
  207.  
  208.     //
  209.     // Create new key or open existing key
  210.     //
  211.  
  212.     returnValue = RegCreateKeyEx (RootKey, KeyName, 0, TEXT(""), 0, KEY_ALL_ACCESS, NULL, ®istryKey, &disposition);
  213.     if (returnValue != ERROR_SUCCESS)
  214.         return returnValue;
  215.  
  216.     //
  217.     // Write the security descriptor
  218.     //
  219.  
  220.     returnValue = RegSetValueEx (registryKey, ValueName, 0, REG_BINARY, (LPBYTE) SD, GetSecurityDescriptorLength (SD));
  221.     if (returnValue != ERROR_SUCCESS)
  222.         return returnValue;
  223.  
  224.     RegCloseKey (registryKey);
  225.  
  226.     return ERROR_SUCCESS;
  227. }
  228.  
  229. DWORD
  230. GetNamedValueSD (
  231.     HKEY RootKey,
  232.     LPTSTR KeyName,
  233.     LPTSTR ValueName,
  234.     SECURITY_DESCRIPTOR **SD,
  235.     BOOL *NewSD
  236.     )
  237. {
  238.     DWORD               returnValue;
  239.     HKEY                registryKey;
  240.     DWORD               valueType;
  241.     DWORD               valueSize;
  242.  
  243.     *NewSD = FALSE;
  244.  
  245.     //
  246.     // Get the security descriptor from the named value. If it doesn't
  247.     // exist, create a fresh one.
  248.     //
  249.  
  250.     returnValue = RegOpenKeyEx (RootKey, KeyName, 0, KEY_ALL_ACCESS, ®istryKey);
  251.  
  252.     if (returnValue != ERROR_SUCCESS)
  253.     {
  254.         if (returnValue == ERROR_FILE_NOT_FOUND)
  255.         {
  256.             *SD = NULL;
  257.             returnValue = CreateNewSD (SD);
  258.             if (returnValue != ERROR_SUCCESS)
  259.                 return returnValue;
  260.  
  261.             *NewSD = TRUE;
  262.             return ERROR_SUCCESS;
  263.         } else
  264.             return returnValue;
  265.     }
  266.  
  267.     returnValue = RegQueryValueEx (registryKey, ValueName, NULL, &valueType, NULL, &valueSize);
  268.  
  269.     if (returnValue && returnValue != ERROR_INSUFFICIENT_BUFFER)
  270.     {
  271.         *SD = NULL;
  272.         returnValue = CreateNewSD (SD);
  273.         if (returnValue != ERROR_SUCCESS)
  274.             return returnValue;
  275.  
  276.         *NewSD = TRUE;
  277.     } else
  278.     {
  279.         *SD = (SECURITY_DESCRIPTOR *) malloc (valueSize);
  280.  
  281.         returnValue = RegQueryValueEx (registryKey, ValueName, NULL, &valueType, (LPBYTE) *SD, &valueSize);
  282.         if (returnValue)
  283.         {
  284.             free (*SD);
  285.  
  286.             *SD = NULL;
  287.             returnValue = CreateNewSD (SD);
  288.             if (returnValue != ERROR_SUCCESS)
  289.                 return returnValue;
  290.  
  291.             *NewSD = TRUE;
  292.         }
  293.     }
  294.  
  295.     RegCloseKey (registryKey);
  296.  
  297.     return ERROR_SUCCESS;
  298. }
  299.  
  300. DWORD
  301. ListNamedValueSD (
  302.     HKEY RootKey,
  303.     LPTSTR KeyName,
  304.     LPTSTR ValueName
  305.     )
  306. {
  307.     DWORD               returnValue;
  308.     SECURITY_DESCRIPTOR *sd;
  309.     BOOL                present;
  310.     BOOL                defaultDACL;
  311.     PACL                dacl;
  312.     BOOL                newSD = FALSE;
  313.  
  314.     returnValue = GetNamedValueSD (RootKey, KeyName, ValueName, &sd, &newSD);
  315.  
  316.     if ((returnValue != ERROR_SUCCESS) || (newSD == TRUE))
  317.     {
  318.         _tprintf (TEXT("<Using Default Permissions>\n"));
  319.         free (sd);
  320.         return returnValue;
  321.     }
  322.  
  323.     if (!GetSecurityDescriptorDacl (sd, &present, &dacl, &defaultDACL))
  324.     {
  325.         free (sd);
  326.         return GetLastError();
  327.     }
  328.  
  329.     if (!present)
  330.     {
  331.         _tprintf (TEXT("<Access is denied to everyone>\n"));
  332.         free (sd);
  333.         return ERROR_SUCCESS;
  334.     }
  335.  
  336.     ListACL (dacl);
  337.  
  338.     free (sd);
  339.  
  340.     return ERROR_SUCCESS;
  341. }
  342.  
  343. DWORD
  344. AddPrincipalToNamedValueSD (
  345.     HKEY RootKey,
  346.     LPTSTR KeyName,
  347.     LPTSTR ValueName,
  348.     LPTSTR Principal,
  349.     BOOL Permit
  350.     )
  351. {
  352.     DWORD               returnValue;
  353.     SECURITY_DESCRIPTOR *sd;
  354.     SECURITY_DESCRIPTOR *sdSelfRelative;
  355.     SECURITY_DESCRIPTOR *sdAbsolute;
  356.     DWORD               secDescSize;
  357.     BOOL                present;
  358.     BOOL                defaultDACL;
  359.     PACL                dacl;
  360.     BOOL                newSD = FALSE;
  361.  
  362.     returnValue = GetNamedValueSD (RootKey, KeyName, ValueName, &sd, &newSD);
  363.  
  364.     //
  365.     // Get security descriptor from registry or create a new one
  366.     //
  367.  
  368.     if (returnValue != ERROR_SUCCESS)
  369.         return returnValue;
  370.  
  371.     if (!GetSecurityDescriptorDacl (sd, &present, &dacl, &defaultDACL))
  372.         return GetLastError();
  373.  
  374.     if (newSD)
  375.     {
  376.         AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, TEXT("SYSTEM"));
  377.         AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, TEXT("INTERACTIVE"));
  378.     }
  379.  
  380.     //
  381.     // Add the Principal that the caller wants added
  382.     //
  383.  
  384.     if (Permit)
  385.         returnValue = AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, Principal); else
  386.         returnValue = AddAccessDeniedACEToACL (&dacl, GENERIC_ALL, Principal);
  387.  
  388.     if (returnValue != ERROR_SUCCESS)
  389.     {
  390.         free (sd);
  391.         return returnValue;
  392.     }
  393.  
  394.     //
  395.     // Make the security descriptor absolute if it isn't new
  396.     //
  397.  
  398.     if (!newSD)
  399.         MakeSDAbsolute ((PSECURITY_DESCRIPTOR) sd, (PSECURITY_DESCRIPTOR *) &sdAbsolute); else
  400.         sdAbsolute = sd;
  401.  
  402.     //
  403.     // Set the discretionary ACL on the security descriptor
  404.     //
  405.  
  406.     if (!SetSecurityDescriptorDacl (sdAbsolute, TRUE, dacl, FALSE))
  407.         return GetLastError();
  408.  
  409.     //
  410.     // Make the security descriptor self-relative so that we can
  411.     // store it in the registry
  412.     //
  413.  
  414.     secDescSize = 0;
  415.     MakeSelfRelativeSD (sdAbsolute, sdSelfRelative, &secDescSize);
  416.     sdSelfRelative = (SECURITY_DESCRIPTOR *) malloc (secDescSize);
  417.     if (!MakeSelfRelativeSD (sdAbsolute, sdSelfRelative, &secDescSize))
  418.         return GetLastError();
  419.  
  420.     //
  421.     // Store the security descriptor in the registry
  422.     //
  423.  
  424.     SetNamedValueSD (RootKey, KeyName, ValueName, sdSelfRelative);
  425.  
  426.     free (sd);
  427.     free (sdSelfRelative);
  428.     free (sdAbsolute);
  429.  
  430.     return ERROR_SUCCESS;
  431. }
  432.  
  433. DWORD
  434. RemovePrincipalFromNamedValueSD (
  435.     HKEY RootKey,
  436.     LPTSTR KeyName,
  437.     LPTSTR ValueName,
  438.     LPTSTR Principal
  439.     )
  440. {
  441.     DWORD               returnValue;
  442.     SECURITY_DESCRIPTOR *sd;
  443.     SECURITY_DESCRIPTOR *sdSelfRelative;
  444.     SECURITY_DESCRIPTOR *sdAbsolute;
  445.     DWORD               secDescSize;
  446.     BOOL                present;
  447.     BOOL                defaultDACL;
  448.     PACL                dacl;
  449.     BOOL                newSD = FALSE;
  450.  
  451.     returnValue = GetNamedValueSD (RootKey, KeyName, ValueName, &sd, &newSD);
  452.  
  453.     //
  454.     // Get security descriptor from registry or create a new one
  455.     //
  456.  
  457.     if (returnValue != ERROR_SUCCESS)
  458.         return returnValue;
  459.  
  460.     if (!GetSecurityDescriptorDacl (sd, &present, &dacl, &defaultDACL))
  461.         return GetLastError();
  462.  
  463.     //
  464.     // If the security descriptor is new, add the required Principals to it
  465.     //
  466.  
  467.     if (newSD)
  468.     {
  469.         AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, TEXT("SYSTEM"));
  470.         AddAccessAllowedACEToACL (&dacl, COM_RIGHTS_EXECUTE, TEXT("INTERACTIVE"));
  471.     }
  472.  
  473.     //
  474.     // Remove the Principal that the caller wants removed
  475.     //
  476.  
  477.     returnValue = RemovePrincipalFromACL (dacl, Principal);
  478.     if (returnValue != ERROR_SUCCESS)
  479.     {
  480.         free (sd);
  481.         return returnValue;
  482.     }
  483.  
  484.     //
  485.     // Make the security descriptor absolute if it isn't new
  486.     //
  487.  
  488.     if (!newSD)
  489.         MakeSDAbsolute ((PSECURITY_DESCRIPTOR) sd, (PSECURITY_DESCRIPTOR *) &sdAbsolute); else
  490.         sdAbsolute = sd;
  491.  
  492.     //
  493.     // Set the discretionary ACL on the security descriptor
  494.     //
  495.  
  496.     if (!SetSecurityDescriptorDacl (sdAbsolute, TRUE, dacl, FALSE))
  497.         return GetLastError();
  498.  
  499.     //
  500.     // Make the security descriptor self-relative so that we can
  501.     // store it in the registry
  502.     //
  503.  
  504.     secDescSize = 0;
  505.     MakeSelfRelativeSD (sdAbsolute, sdSelfRelative, &secDescSize);
  506.     sdSelfRelative = (SECURITY_DESCRIPTOR *) malloc (secDescSize);
  507.     if (!MakeSelfRelativeSD (sdAbsolute, sdSelfRelative, &secDescSize))
  508.         return GetLastError();
  509.  
  510.     //
  511.     // Store the security descriptor in the registry
  512.     //
  513.  
  514.     SetNamedValueSD (RootKey, KeyName, ValueName, sdSelfRelative);
  515.  
  516.     free (sd);
  517.     free (sdSelfRelative);
  518.     free (sdAbsolute);
  519.  
  520.     return ERROR_SUCCESS;
  521. }
  522.