comparison cinst/nssstore_win.c @ 983:427e2e18b8c8

Move Shell functions into util Due to a bug in mingw only one c file may include shlobj.h as there is an unguarded inline definition in there leading to multiple definition errors. Thus the get_program_data get_program_files utility functions.
author Andre Heinecke <andre.heinecke@intevation.de>
date Fri, 29 Aug 2014 17:11:35 +0200
parents 698b6a9bd75e
children 1743895b39b8
comparison
equal deleted inserted replaced
982:85c497b45488 983:427e2e18b8c8
45 #include <stdbool.h> 45 #include <stdbool.h>
46 #include <userenv.h> 46 #include <userenv.h>
47 #include <io.h> 47 #include <io.h>
48 #include <accctrl.h> 48 #include <accctrl.h>
49 #include <aclapi.h> 49 #include <aclapi.h>
50 #include <shlobj.h>
51 50
52 #include "logging.h" 51 #include "logging.h"
53 #include "util.h" 52 #include "util.h"
54 #include "strhelp.h" 53 #include "strhelp.h"
55 54
733 if (piProcInfo.hThread) 732 if (piProcInfo.hThread)
734 CloseHandle (piProcInfo.hThread); 733 CloseHandle (piProcInfo.hThread);
735 return true; 734 return true;
736 } 735 }
737 736
738 /**@brief Create a directory with restricted access rights
739 *
740 * This creates a security attributes structure that restricts
741 * write access to the Administrators group but allows everyone to read files
742 * in that directory.
743 * Basically a very complicated version of mkdir path -m 644
744 *
745 * If the directory exists the permissions of that directory are checked if
746 * they are acceptable and true or false is returned accordingly.
747 *
748 * Code based on msdn example:
749 * http://msdn.microsoft.com/en-us/library/windows/desktop/aa446595%28v=vs.85%29.aspx
750 *
751 * @param[in] path Path of the directory to create
752 *
753 * @returns true on success of if the directory exists, false on error
754 */
755 bool
756 create_restricted_directory (LPWSTR path)
757 {
758 bool retval = false;
759 PSID everyone_SID = NULL,
760 admin_SID = NULL;
761 PACL access_control_list = NULL;
762 PSECURITY_DESCRIPTOR descriptor = NULL;
763 EXPLICIT_ACCESS explicit_access[2];
764 SID_IDENTIFIER_AUTHORITY world_identifier = {SECURITY_WORLD_SID_AUTHORITY},
765 admin_identifier = {SECURITY_NT_AUTHORITY};
766 SECURITY_ATTRIBUTES security_attributes;
767
768 ZeroMemory(&security_attributes, sizeof(security_attributes));
769 ZeroMemory(&explicit_access, 2 * sizeof(EXPLICIT_ACCESS));
770
771 /* Create a well-known SID for the Everyone group. */
772 if(!AllocateAndInitializeSid(&world_identifier, /* top-level identifier */
773 1, /* subauthorties count */
774 SECURITY_WORLD_RID, /* Only one authority */
775 0, 0, 0, 0, 0, 0, 0, /* No other authorities*/
776 &everyone_SID))
777 {
778 PRINTLASTERROR ("Failed to allocate world sid.\n");
779 return false;
780 }
781
782 /* Initialize the first EXPLICIT_ACCESS structure for an ACE.
783 to allow everyone read access */
784 explicit_access[0].grfAccessPermissions = GENERIC_READ; /* Give read access */
785 explicit_access[0].grfAccessMode = SET_ACCESS; /* Overwrite other access for all users */
786 explicit_access[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; /* make it stick */
787 explicit_access[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
788 explicit_access[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
789 explicit_access[0].Trustee.ptstrName = (LPTSTR) everyone_SID;
790
791 /* Create the SID for the BUILTIN\Administrators group. */
792 if(!AllocateAndInitializeSid(&admin_identifier,
793 2,
794 SECURITY_BUILTIN_DOMAIN_RID, /*BUILTIN\ */
795 DOMAIN_ALIAS_RID_ADMINS, /*\Administrators */
796 0, 0, 0, 0, 0, 0, /* No other */
797 &admin_SID))
798 {
799 PRINTLASTERROR ("Failed to allocate admin sid.");
800 goto done;
801 }
802
803 /* explicit_access[1] grants admins full rights for this object and inherits
804 it to the children */
805 explicit_access[1].grfAccessPermissions = GENERIC_ALL;
806 explicit_access[1].grfAccessMode = SET_ACCESS;
807 explicit_access[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
808 explicit_access[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
809 explicit_access[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
810 explicit_access[1].Trustee.ptstrName = (LPTSTR) admin_SID;
811
812 /* Set up the ACL structure. */
813 if (ERROR_SUCCESS != SetEntriesInAcl(2, explicit_access, NULL, &access_control_list))
814 {
815 PRINTLASTERROR ("Failed to set up Acl.");
816 goto done;
817 }
818
819 /* Initialize a security descriptor */
820 descriptor = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR,
821 SECURITY_DESCRIPTOR_MIN_LENGTH);
822 if (descriptor == NULL)
823 {
824 PRINTLASTERROR("Failed to allocate descriptor.");
825 goto done;
826 }
827
828 if (!InitializeSecurityDescriptor(descriptor,
829 SECURITY_DESCRIPTOR_REVISION))
830 {
831 PRINTLASTERROR("Failed to initialize descriptor.");
832 goto done;
833 }
834
835 /* Now we add the ACL to the the descriptor */
836 if (!SetSecurityDescriptorDacl(descriptor,
837 TRUE, /* bDaclPresent flag */
838 access_control_list,
839 FALSE)) /* not a default DACL */
840 {
841 PRINTLASTERROR("Failed to set security descriptor.");
842 goto done;
843 }
844
845 /* Finally set up the security attributes structure */
846 security_attributes.nLength = sizeof (SECURITY_ATTRIBUTES);
847 security_attributes.lpSecurityDescriptor = descriptor;
848 security_attributes.bInheritHandle = FALSE;
849
850 /* Use the security attributes to create the directory */
851 if (!CreateDirectoryW(path, &security_attributes))
852 {
853 DWORD err = GetLastError();
854 if (err == ERROR_ALREADY_EXISTS)
855 {
856 /* Verify that the directory has the correct rights */
857 // TODO
858 retval = true;
859 goto done;
860 }
861 ERRORPRINTF ("Failed to create directory. Err: %lu", err);
862 }
863 retval = true;
864
865 done:
866
867 if (everyone_SID)
868 FreeSid(everyone_SID);
869 if (admin_SID)
870 FreeSid(admin_SID);
871 if (access_control_list)
872 LocalFree(access_control_list);
873 if (descriptor)
874 LocalFree(descriptor);
875
876 return retval;
877 }
878
879 /**@brief Writes the selection file containing the instructions 737 /**@brief Writes the selection file containing the instructions
880 * 738 *
881 * If the process is running elevated the instructions are 739 * If the process is running elevated the instructions are
882 * written to the global ProgramData directory otherwise 740 * written to the global ProgramData directory otherwise
883 * they are written in the directory of the current user. 741 * they are written in the directory of the current user.
892 wchar_t * 750 wchar_t *
893 write_selection_file (char **to_install, char **to_remove) 751 write_selection_file (char **to_install, char **to_remove)
894 { 752 {
895 wchar_t *folder_name = NULL, 753 wchar_t *folder_name = NULL,
896 *path = NULL; 754 *path = NULL;
897 HRESULT result = E_FAIL;
898 HANDLE hFile = NULL; 755 HANDLE hFile = NULL;
899 size_t path_len; 756 size_t path_len;
900 757
901 result = SHGetKnownFolderPath (&FOLDERID_ProgramData, /* Get program data dir */ 758 folder_name = get_program_data_folder();
902 KF_FLAG_CREATE | /* Create if it does not exist */ 759 if (!folder_name)
903 KF_FLAG_INIT, /* Initialize it if created */ 760 {
904 INVALID_HANDLE_VALUE, /* Get it for the default user */ 761 ERRORPRINTF("Failed to look up ProgramData folder.\n");
905 &folder_name);
906
907 if (result != S_OK)
908 {
909 PRINTLASTERROR ("Failed to get folder path");
910 return NULL; 762 return NULL;
911 } 763 }
912 764
913 path_len = wcslen (folder_name) + wcslen (APPNAME) + 2; /* path + dirsep + \0 */ 765 path_len = wcslen (folder_name) + wcslen (APPNAME) + 2; /* path + dirsep + \0 */
914 path_len += wcslen (SELECTION_FILE_NAME) + 1; /* filename + dirsep */ 766 path_len += wcslen (SELECTION_FILE_NAME) + 1; /* filename + dirsep */

http://wald.intevation.org/projects/trustbridge/