Change the ACL on our %temp% directories (bug #1125)

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6657 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2015-12-07 20:49:46 +00:00
parent 0cac95475e
commit d7d6c3561d
7 changed files with 63 additions and 16 deletions

View file

@ -10,10 +10,10 @@ Released on ? ?th, 201?
\b RequestExecutionLevel now defaults to \c{admin}
\b FileReadUTF16LE now skips the optional BOM at the start of a file
\b LoadLibrary security hardening to prevent dll hijacking
\b FileReadUTF16LE now skips the optional BOM at the start of a file
\S2{} Minor Changes
\b Fixed System plugin GUID type output bug on Win98

View file

@ -3592,8 +3592,8 @@ again:
// Delete $0 [simple, nothing that could clash with special temp permissions]
ret=add_entry_direct(EW_DELETEFILE, zero_offset, DEL_SIMPLE);
if (ret != PS_OK) return ret;
// CraeteDirectory $0 - a dir instead of that temp file
ret=add_entry_direct(EW_CREATEDIR, zero_offset);
// CreateDirectory $0 - a dir instead of that temp file
ret=add_entry_direct(EW_CREATEDIR, zero_offset, 0, 1);
if (ret != PS_OK) return ret;
// IfErrors Initialize_____Plugins_error - detect errors
ret=add_entry_direct(EW_IFFLAG, ns_label.add(_T("Initialize_____Plugins_error"),0), 0, FLAG_OFFSET(exec_error));

View file

@ -74,7 +74,7 @@ TCHAR *ValidateTempDir()
if (!validpathspec(state_temp_dir))
return NULL;
addtrailingslash(state_temp_dir);
CreateDirectory(state_temp_dir, NULL);
CreateNormalDirectory(state_temp_dir);
// state_language is used as a temp var here
return my_GetTempFileName(state_language, state_temp_dir);
}
@ -273,16 +273,18 @@ EXTERN_C void NSISWinMainNOCRT()
}
else
{
int x;
int x, admin = UserIsAdminGrpMember();
mystrcat(state_temp_dir,_T("~nsu.tmp"));
mystrcat(state_temp_dir,_T("~nsu"));
if (admin) mystrcat(state_temp_dir,_T("A")); // Don't lock down the directory used by non-admins
mystrcat(state_temp_dir,_T(".tmp"));
// check if already running from uninstaller temp dir
// this prevents recursive uninstaller calls
if (!lstrcmpi(state_temp_dir,state_exe_directory))
goto end;
CreateDirectory(state_temp_dir,NULL);
admin ? CreateRestrictedDirectory(state_temp_dir) : CreateNormalDirectory(state_temp_dir);
SetCurrentDirectory(state_temp_dir);
if (!(*state_install_directory))

View file

@ -331,20 +331,23 @@ static int NSISCALL ExecuteEntry(entry *entry_)
TCHAR *buf1=GetStringFromParm(-0x10);
log_printf3(_T("CreateDirectory: \"%s\" (%d)"),buf1,parm1);
{
TCHAR *p = skip_root(buf1);
TCHAR c = _T('c');
TCHAR *p = skip_root(buf1), c = _T('c');
if (p)
{
while (c)
{
DWORD ec;
p = findchar(p, _T('\\'));
c = *p;
*p = 0;
if (!CreateDirectory(buf1, NULL))
c = *p, *p = 0;
if (!c && parm2 && UserIsAdminGrpMember()) // Lock down the final directory?
ec = CreateRestrictedDirectory(buf1);
else
ec = CreateNormalDirectory(buf1);
if (ec)
{
if (GetLastError() != ERROR_ALREADY_EXISTS)
if (ec != ERROR_ALREADY_EXISTS)
{
log_printf3(_T("CreateDirectory: can't create \"%s\" (err=%d)"),buf1,GetLastError());
log_printf3(_T("CreateDirectory: can't create \"%s\" (err=%d)"),buf1,ec);
exec_error++;
}
else if ((GetFileAttributes(buf1) & FILE_ATTRIBUTE_DIRECTORY) == 0)

View file

@ -61,7 +61,7 @@ enum
EW_BRINGTOFRONT, // BringToFront: 0
EW_CHDETAILSVIEW, // SetDetailsView: 2 [listaction,buttonaction]
EW_SETFILEATTRIBUTES, // SetFileAttributes: 2 [filename, attributes]
EW_CREATEDIR, // Create directory: 2, [path, ?update$INSTDIR]
EW_CREATEDIR, // Create directory: 2, [path, ?update$INSTDIR, ?restrictAcl]
EW_IFFILEEXISTS, // IfFileExists: 3, [file name, jump amount if exists, jump amount if not exists]
EW_SETFLAG, // Sets a flag: 2 [id, data]
EW_IFFLAG, // If a flag: 4 [on, off, id, new value mask]

View file

@ -56,6 +56,38 @@ const NSIS_STRING*const g_usrvarsstart = (const NSIS_STRING*const) g_usrvarssect
# endif
#endif
const UINT32 g_restrictedacl[] = {
0x00340002, 0x00000002, // ACL (ACL_REVISION2, 2 ACEs)
0x00180300, // ACCESS_ALLOWED_ACE:ACE_HEADER (ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
0x10000000, // ACCESS_ALLOWED_ACE:ACCESS_MASK: GENERIC_ALL
0x00000201, 0x05000000, 0x00000020, 0x00000220, // ACCESS_ALLOWED_ACE:SID (BUILTIN\Administrators) NOTE: GetAdminGrpSid() relies on this being the first SID in the ACL
0x00140300, // ACCESS_ALLOWED_ACE:ACE_HEADER (ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE|OBJECT_INHERIT_ACE)
0x00130041, // ACCESS_ALLOWED_ACE:ACCESS_MASK: DELETE|READ_CONTROL|SYNCHRONIZE|FILE_DELETE_CHILD|FILE_LIST_DIRECTORY
0x00000101, 0x01000000, 0x00000000 // ACCESS_ALLOWED_ACE:SID (WORLD\Everyone)
};
DWORD NSISCALL CreateRestrictedDirectory(LPCTSTR path)
{
const SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|PROTECTED_DACL_SECURITY_INFORMATION;
PSID admingrpsid = GetAdminGrpSid();
SECURITY_DESCRIPTOR sd = { 1, 0, SE_DACL_PRESENT, admingrpsid, admingrpsid, NULL, GetAdminGrpAcl() };
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), &sd, FALSE };
DWORD ec = CreateDirectory(path, &sa) ? ERROR_SUCCESS : GetLastError();
if (ERROR_ALREADY_EXISTS == ec)
ec = SetFileSecurity(path, si, &sd) ? ERROR_SUCCESS : GetLastError();
return ec;
}
DWORD NSISCALL CreateNormalDirectory(LPCTSTR path)
{
return CreateDirectory(path, NULL) ? ERROR_SUCCESS : GetLastError();
}
BOOL NSISCALL UserIsAdminGrpMember()
{
FARPROC iuaa = myGetProcAddress(MGA_IsUserAnAdmin);
return iuaa && ((BOOL(WINAPI*)())iuaa)();
}
HANDLE NSISCALL myCreateProcess(TCHAR *cmd)
{
PROCESS_INFORMATION ProcInfo;
@ -1070,6 +1102,7 @@ struct MGA_FUNC MGA_FUNCS[] = {
{"ADVAPI32", "RegDeleteKeyExW"},
#endif
{"ADVAPI32", "InitiateShutdownW"},
{"SHELL32", (CHAR*) 680}, // IsUserAnAdmin
{"SHLWAPI", "SHAutoComplete"},
{"SHFOLDER", "SHGetFolderPathW"},
{"VERSION", "GetFileVersionInfoSizeW"},
@ -1082,6 +1115,7 @@ struct MGA_FUNC MGA_FUNCS[] = {
{"KERNEL32", "GetUserDefaultUILanguage"},
{"ADVAPI32", "RegDeleteKeyExA"},
{"ADVAPI32", "InitiateShutdownA"},
{"SHELL32", (CHAR*) 680}, // IsUserAnAdmin
{"SHLWAPI", "SHAutoComplete"},
{"SHFOLDER", "SHGetFolderPathA"},
{"VERSION", "GetFileVersionInfoSizeA"},

View file

@ -86,6 +86,13 @@ extern TCHAR g_log_file[1024];
#define LogData2Hex(x1,x2,x3,x4)
#endif
extern const UINT32 g_restrictedacl[];
#define GetAdminGrpAcl() ( (PACL) g_restrictedacl )
#define GetAdminGrpSid() ( (PSID) &g_restrictedacl[4] )
BOOL NSISCALL UserIsAdminGrpMember(); // Does not check integrity level, returns true if the process has a non-deny administrators group ACE in the token
DWORD NSISCALL CreateRestrictedDirectory(LPCTSTR path);
DWORD NSISCALL CreateNormalDirectory(LPCTSTR path);
HANDLE NSISCALL myCreateProcess(TCHAR *cmd);
int NSISCALL my_MessageBox(const TCHAR *text, UINT type);
@ -126,6 +133,7 @@ enum myGetProcAddressFunctions {
MGA_RegDeleteKeyEx,
#endif
MGA_InitiateShutdown,
MGA_IsUserAnAdmin,
MGA_SHAutoComplete, // x64 can link to shlwapi directly but as long as MGA_SHGetFolderPath is used we can stick with myGetProcAddress
MGA_SHGetFolderPath, // TODO: This can probably call something else directly on x64
#ifdef NSIS_SUPPORT_GETDLLVERSION