Example #1
0
HRESULT COpcSecurity::AttachObject(HANDLE hObject)
{
	HRESULT hr;
	DWORD dwSize = 0;
	PSECURITY_DESCRIPTOR pSD = NULL;

	GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
		DACL_SECURITY_INFORMATION, pSD, 0, &dwSize);

	hr = GetLastError();
	if (hr != ERROR_INSUFFICIENT_BUFFER)
		return HRESULT_FROM_WIN32(hr);

	pSD = (PSECURITY_DESCRIPTOR) malloc(dwSize);
	if (pSD == NULL)
		return E_OUTOFMEMORY;

	if (!GetKernelObjectSecurity(hObject, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
		DACL_SECURITY_INFORMATION, pSD, dwSize, &dwSize))
	{
		hr = HRESULT_FROM_WIN32(GetLastError());
		free(pSD);
		return hr;
	}

	hr = Attach(pSD);
	free(pSD);
	return hr;
}
Example #2
0
static VOID GetRemotePrivilegesGet(char *FileName, PDWORD dwRemotePrivileges)
{
    HANDLE hFile;

    *dwRemotePrivileges = 0;

    /* see if we have the SeBackupPrivilege */

    hFile = CreateFileA(
        FileName,
        ACCESS_SYSTEM_SECURITY | GENERIC_READ | READ_CONTROL,
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS,
        NULL
        );

    if(hFile != INVALID_HANDLE_VALUE) {
        /* no remote way to determine SeBackupPrivilege -- just try a read
           to simulate it */
        SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
        PSECURITY_DESCRIPTOR sd;
        DWORD cbBuf = 0;

        GetKernelObjectSecurity(hFile, si, NULL, cbBuf, &cbBuf);

        if(ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
            if((sd = HeapAlloc(GetProcessHeap(), 0, cbBuf)) != NULL) {
                if(GetKernelObjectSecurity(hFile, si, sd, cbBuf, &cbBuf)) {
                    *dwRemotePrivileges |= OVERRIDE_BACKUP;
                }
                HeapFree(GetProcessHeap(), 0, sd);
            }
        }

        CloseHandle(hFile);
    } else {

        /* see if we have the SeSecurityPrivilege */
        /* note we don't need this if we have SeBackupPrivilege */

        hFile = CreateFileA(
            FileName,
            ACCESS_SYSTEM_SECURITY,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* maximum sharing */
            NULL,
            OPEN_EXISTING,
            0,
            NULL
            );

        if(hFile != INVALID_HANDLE_VALUE) {
            CloseHandle(hFile);
            *dwRemotePrivileges |= OVERRIDE_SACL;
        }
    }
}
Example #3
0
static NTSTATUS GetSecurityByName(FSP_FILE_SYSTEM *FileSystem,
    PWSTR FileName, PUINT32 PFileAttributes,
    PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize)
{
    PTFS *Ptfs = (PTFS *)FileSystem->UserContext;
    WCHAR FullPath[FULLPATH_SIZE];
    HANDLE Handle;
    FILE_ATTRIBUTE_TAG_INFO AttributeTagInfo;
    DWORD SecurityDescriptorSizeNeeded;
    NTSTATUS Result;

    if (!ConcatPath(Ptfs, FileName, FullPath))
        return STATUS_OBJECT_NAME_INVALID;

    Handle = CreateFileW(FullPath,
        FILE_READ_ATTRIBUTES | READ_CONTROL, 0, 0,
        OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
    if (INVALID_HANDLE_VALUE == Handle)
    {
        Result = FspNtStatusFromWin32(GetLastError());
        goto exit;
    }

    if (0 != PFileAttributes)
    {
        if (!GetFileInformationByHandleEx(Handle,
            FileAttributeTagInfo, &AttributeTagInfo, sizeof AttributeTagInfo))
        {
            Result = FspNtStatusFromWin32(GetLastError());
            goto exit;
        }

        *PFileAttributes = AttributeTagInfo.FileAttributes;
    }

    if (0 != PSecurityDescriptorSize)
    {
        if (!GetKernelObjectSecurity(Handle,
            OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
            SecurityDescriptor, (DWORD)*PSecurityDescriptorSize, &SecurityDescriptorSizeNeeded))
        {
            *PSecurityDescriptorSize = SecurityDescriptorSizeNeeded;
            Result = FspNtStatusFromWin32(GetLastError());
            goto exit;
        }

        *PSecurityDescriptorSize = SecurityDescriptorSizeNeeded;
    }

    Result = STATUS_SUCCESS;

exit:
    if (INVALID_HANDLE_VALUE != Handle)
        CloseHandle(Handle);

    return Result;
}
Example #4
0
static NTSTATUS GetSecurity(FSP_FILE_SYSTEM *FileSystem,
    PVOID FileContext,
    PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize)
{
    HANDLE Handle = HandleFromContext(FileContext);
    DWORD SecurityDescriptorSizeNeeded;

    if (!GetKernelObjectSecurity(Handle,
        OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
        SecurityDescriptor, (DWORD)*PSecurityDescriptorSize, &SecurityDescriptorSizeNeeded))
    {
        *PSecurityDescriptorSize = SecurityDescriptorSizeNeeded;
        return FspNtStatusFromWin32(GetLastError());
    }

    *PSecurityDescriptorSize = SecurityDescriptorSizeNeeded;

    return STATUS_SUCCESS;
}
Example #5
0
// https://ru.wikipedia.org/wiki/DACL + https://github.com/hfiref0x/WinObjEx64/tree/master/Source
BOOL AddAllowSidForDevice(PWCHAR wchPath, PSID lpSid, DWORD dwSidLength) {
	OBJECT_ATTRIBUTES ObjAtt;
	RtlZeroMemory(&ObjAtt, sizeof(ObjAtt));

	UNICODE_STRING UserModeDeviceName;

	WCHAR PathBuffer[MAX_PATH] = { 0 };

	wcscpy_s(PathBuffer, L"\\??\\");
	wcscat_s(PathBuffer, wchPath);

	UserModeDeviceName.Buffer = PathBuffer;
	UserModeDeviceName.Length = (USHORT)(wcslen(PathBuffer) * sizeof(WCHAR));
	UserModeDeviceName.MaximumLength = (USHORT)(UserModeDeviceName.Length + sizeof(WCHAR));
	InitializeObjectAttributes(&ObjAtt, &UserModeDeviceName, 0, 0, 0);

	HANDLE hFile;
	IO_STATUS_BLOCK IoStatusBlock;
	NTSTATUS status = ntdll_ZwOpenFile(&hFile, WRITE_DAC | READ_CONTROL, &ObjAtt, &IoStatusBlock, 0, 0);
	if (status != STATUS_SUCCESS) {
		DebugOut("ZwOpenFile(..., %S,...) failed! (status=%x)\n", wchPath, status);
		return FALSE;
	}

	DWORD LastError;
	SECURITY_DESCRIPTOR *lpSd = NULL;	// адрес дескриптора безопасности
	DWORD dwSdLength = 0;				// длина SD
	if (!GetKernelObjectSecurity(hFile, DACL_SECURITY_INFORMATION, NULL, dwSdLength, &dwSdLength)) {
		LastError = GetLastError();
		if (LastError == ERROR_INSUFFICIENT_BUFFER) {
			dwSdLength += 1000; // !! FIX_ME
			lpSd = (SECURITY_DESCRIPTOR*)malloc(dwSdLength);
			if (!GetKernelObjectSecurity(hFile, DACL_SECURITY_INFORMATION, lpSd, dwSdLength, &dwSdLength)) {
				DebugOut("GetKernelObjectSecurity[2](...) failed! (LastError=0x%x)\n", GetLastError());
				CloseHandle(hFile);
				return FALSE;
			}
		} else {
			DebugOut("GetKernelObjectSecurity[1](...) failed! (LastError=0x%x)\n", LastError);
			CloseHandle(hFile);
			return FALSE;
		}
	}
	ACL* lpOldDacl;						// указатель на старый DACL
	BOOL bDaclPresent;					// признак присутствия списка DACL
	BOOL bDaclDefaulted;				// признак списка DACL по умолчанию
	if (!GetSecurityDescriptorDacl(lpSd, &bDaclPresent, &lpOldDacl, &bDaclDefaulted)) { // получаем список DACL из дескриптора безопасности
		DebugOut("GetSecurityDescriptorDacl(...) failed! (LastError=0x%x)\n", GetLastError());
		CloseHandle(hFile);
		return FALSE;
	}
	DWORD dwDaclLength = lpOldDacl->AclSize + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + dwSidLength; // определяем длину нового DACL
	ACL* lpNewDacl = (ACL*)malloc(dwDaclLength);
	if (!InitializeAcl(lpNewDacl, dwDaclLength, ACL_REVISION)) { // инициализируем новый DACL
		DebugOut("InitializeAcl(...) failed! (LastError=0x%x)\n", GetLastError());
		free(lpNewDacl);
		CloseHandle(hFile);
		return FALSE;
	}
	if (!AddAccessAllowedAce(lpNewDacl, ACL_REVISION,ACCOUNT_ALLOW_RIGHTS, lpSid)) { // добавляем новый элемент в новый DACL
		DebugOut("AddAccessAllowedAce(...) failed! (LastError=0x%x)\n", GetLastError());
		free(lpNewDacl);
		CloseHandle(hFile);
		return FALSE;
	}
	LPVOID lpAce;						// указатель на элемент ACE
	if (!GetAce(lpOldDacl, 0, &lpAce)) { // получаем адрес первого ACE в старом списке DACL
		DebugOut("GetAce(...) failed! (LastError=0x%x)\n", GetLastError());
		free(lpNewDacl);
		CloseHandle(hFile);
		return FALSE;
	}
	// переписываем элементы из старого DACL в новый DACL
	if (bDaclPresent) {
		if (!AddAce(lpNewDacl, ACL_REVISION, MAXDWORD, lpAce, lpOldDacl->AclSize - sizeof(ACL))) {
			DebugOut("AddAce(...) failed! (LastError=0x%x)\n", GetLastError());
			free(lpNewDacl);
			CloseHandle(hFile);
			return FALSE;
		}
	}
	if (!IsValidAcl(lpNewDacl)) { // проверяем достоверность DACL
		DebugOut("IsValidAcl(...) == FALSE! (LastError=0x%x)\n", GetLastError());
		free(lpNewDacl);
		CloseHandle(hFile);
		return FALSE;
	}
	SECURITY_DESCRIPTOR sdAbsoluteSd;	// абсолютный формат SD
	if (!InitializeSecurityDescriptor(&sdAbsoluteSd, SECURITY_DESCRIPTOR_REVISION)) { // создаем новый дескриптор безопасности в абсолютной форме
		DebugOut("InitializeSecurityDescriptor(...) failed! (LastError=0x%x)\n", GetLastError());
		free(lpNewDacl);
		CloseHandle(hFile);
		return FALSE;
	}
	if (!SetSecurityDescriptorDacl(&sdAbsoluteSd, TRUE, lpNewDacl, FALSE)) { // устанавливаем DACL  в новый дескриптор безопасности
		DebugOut("SetSecurityDescriptorDacl(...) failed! (LastError=0x%x)\n", GetLastError());
		free(lpNewDacl);
		CloseHandle(hFile);
		return FALSE;
	}

	// проверяем структуру дескриптора безопасности
	if (!IsValidSecurityDescriptor(&sdAbsoluteSd)) {
		DebugOut("IsValidSecurityDescriptor(...) == FALSE! (LastError=0x%x)\n", GetLastError());
		free(lpNewDacl);
		CloseHandle(hFile);
		return FALSE;
	}
	
	if (!SetKernelObjectSecurity(hFile, DACL_SECURITY_INFORMATION, &sdAbsoluteSd)) { // устанавливаем новый дескриптор безопасности
		DebugOut("IsValidSecurityDescriptor(...) == FALSE! (LastError=0x%x)\n", GetLastError());
		free(lpNewDacl);
		CloseHandle(hFile);
		return FALSE;
	}
	free(lpNewDacl);
	CloseHandle(hFile);

	DebugOut("ACL Rules applyed to \"%S\"\n", PathBuffer);

	return TRUE;
}
Example #6
0
static VOID Test(PWSTR Prefix)
{
    static PWSTR Sddl = L"D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GA;;;WD)";
    static const GUID ReparseGuid =
        { 0x2cf25cfa, 0x41af, 0x4796, { 0xb5, 0xef, 0xac, 0xa3, 0x85, 0x3, 0xe2, 0xd8 } };
    WCHAR FileName[1024], VolumeName[MAX_PATH];
    PSECURITY_DESCRIPTOR SecurityDescriptor;
    HANDLE Handle;
    BOOL Success;
    UINT8 RdBuffer[4096], WrBuffer[4096];
    REPARSE_GUID_DATA_BUFFER ReparseDataBuf;
    DWORD BytesTransferred, Offset;
    WIN32_FIND_DATAW FindData;
    WIN32_FIND_STREAM_DATA FindStreamData;

    memset(WrBuffer, 'B', sizeof WrBuffer);

    Success = ConvertStringSecurityDescriptorToSecurityDescriptorW(
        Sddl, SDDL_REVISION_1, &SecurityDescriptor, 0);
    ASSERT(Success);

    wsprintfW(FileName, L"%s\\", Prefix);
    Success = GetVolumeInformationW(FileName, VolumeName, MAX_PATH, 0, 0, 0, 0, 0);
    ASSERT(Success);

    wsprintfW(FileName, L"%s\\", Prefix);
    Success = SetVolumeLabelW(FileName, VolumeName);
    //ASSERT(Success);

    wsprintfW(FileName, L"%s\\fscrash", Prefix);
    Success = CreateDirectoryW(FileName, 0);
    ASSERT(Success);

    wsprintfW(FileName, L"%s\\fscrash\\file0", Prefix);
    Handle = CreateFileW(FileName,
        GENERIC_ALL, 0, 0,
        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    ASSERT(INVALID_HANDLE_VALUE != Handle);
    Success = CloseHandle(Handle);
    ASSERT(Success);

    wsprintfW(FileName, L"%s\\fscrash\\file0", Prefix);
    Handle = CreateFileW(FileName,
        GENERIC_ALL, 0, 0,
        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    ASSERT(INVALID_HANDLE_VALUE != Handle);

    Success = WriteFile(Handle, WrBuffer, sizeof WrBuffer, &BytesTransferred, 0);
    ASSERT(Success);
    ASSERT(sizeof WrBuffer == BytesTransferred);

    Success = FlushFileBuffers(Handle);
    ASSERT(Success);

    Offset = SetFilePointer(Handle, 0, 0, FILE_BEGIN);
    ASSERT(0 == Offset);

    Success = ReadFile(Handle, RdBuffer, sizeof RdBuffer, &BytesTransferred, 0);
    ASSERT(Success);
    ASSERT(sizeof WrBuffer == BytesTransferred);

    Offset = SetFilePointer(Handle, 0, 0, FILE_BEGIN);
    ASSERT(0 == Offset);

    Success = SetEndOfFile(Handle);
    ASSERT(Success);

    Offset = GetFileSize(Handle, 0);
    ASSERT(0 == Offset);

    Success = LockFile(Handle, 0, 0, 1, 0);
    ASSERT(Success);

    Success = UnlockFile(Handle, 0, 0, 1, 0);
    ASSERT(Success);

    Success = SetKernelObjectSecurity(Handle, DACL_SECURITY_INFORMATION, SecurityDescriptor);
    ASSERT(Success);

    Success = GetKernelObjectSecurity(Handle, DACL_SECURITY_INFORMATION, 0, 0, &BytesTransferred);
    ASSERT(!Success);
    ASSERT(ERROR_INSUFFICIENT_BUFFER == GetLastError());

    ReparseDataBuf.ReparseTag = 0x1234;
    ReparseDataBuf.ReparseDataLength = 0;
    ReparseDataBuf.Reserved = 0;
    memcpy(&ReparseDataBuf.ReparseGuid, &ReparseGuid, sizeof ReparseGuid);

    Success = DeviceIoControl(Handle, FSCTL_SET_REPARSE_POINT,
        &ReparseDataBuf, REPARSE_GUID_DATA_BUFFER_HEADER_SIZE + ReparseDataBuf.ReparseDataLength,
        0, 0,
        &BytesTransferred, 0);
    ASSERT(Success);

    Success = CloseHandle(Handle);
    ASSERT(Success);

    wsprintfW(FileName, L"%s\\fscrash\\*", Prefix);
    Handle = FindFirstFileW(FileName, &FindData);
    ASSERT(INVALID_HANDLE_VALUE != Handle);
    do
    {
    } while (FindNextFileW(Handle, &FindData));
    ASSERT(ERROR_NO_MORE_FILES == GetLastError());
    Success = FindClose(Handle);
    ASSERT(Success);

    wsprintfW(FileName, L"%s\\fscrash\\file0", Prefix);
    Handle = FindFirstStreamW(FileName, FindStreamInfoStandard, &FindStreamData, 0);
    ASSERT(INVALID_HANDLE_VALUE != Handle);
    do
    {
    } while (FindNextStreamW(Handle, &FindStreamData));
    ASSERT(ERROR_HANDLE_EOF == GetLastError());
    Success = FindClose(Handle);
    ASSERT(Success);

    wsprintfW(FileName, L"%s\\fscrash\\file0", Prefix);
    Success = DeleteFileW(FileName);
    ASSERT(Success);

    wsprintfW(FileName, L"%s\\fscrash", Prefix);
    Success = RemoveDirectoryW(FileName);
    ASSERT(Success);

    LocalFree(SecurityDescriptor);
}
Example #7
0
BOOL SecurityGet(
    char *resource,
    PVOLUMECAPS VolumeCaps,
    unsigned char *buffer,
    DWORD *cbBuffer
    )
{
    HANDLE hFile;
    DWORD dwDesiredAccess;
    DWORD dwFlags;
    PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)buffer;
    SECURITY_INFORMATION RequestedInfo;
    BOOL bBackupPrivilege = FALSE;
    BOOL bSaclPrivilege = FALSE;
    BOOL bSuccess = FALSE;

    DWORD cchResourceLen;

    if(!bZipInitialized) if(!Initialize()) return FALSE;

    /* see if we are dealing with a directory */
    /* rely on the fact resource has a trailing [back]slash, rather
       than calling expensive GetFileAttributes() */

    cchResourceLen = lstrlenA(resource);

    if(resource[cchResourceLen-1] == '/' || resource[cchResourceLen-1] == '\\')
        VolumeCaps->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;

    /* setup privilege usage based on if told we can use privileges, and if so,
       what privileges we have */

    if(VolumeCaps->bUsePrivileges) {
        if(VolumeCaps->bRemote) {
            /* use remotely determined privileges */
            if(VolumeCaps->dwRemotePrivileges & OVERRIDE_BACKUP)
                bBackupPrivilege = TRUE;

            if(VolumeCaps->dwRemotePrivileges & OVERRIDE_SACL)
                bSaclPrivilege = TRUE;
        } else {
            /* use local privileges */
            bBackupPrivilege = g_bBackupPrivilege;
            bSaclPrivilege = g_bZipSaclPrivilege;
        }
    }

    /* always try to read the basic security information:  Dacl, Owner, Group */

    dwDesiredAccess = READ_CONTROL;

    RequestedInfo = OWNER_SECURITY_INFORMATION |
                    GROUP_SECURITY_INFORMATION |
                    DACL_SECURITY_INFORMATION;

    /* if we have the SeBackupPrivilege or SeSystemSecurityPrivilege, read
       the Sacl, too */

    if(bBackupPrivilege || bSaclPrivilege) {
        dwDesiredAccess |= ACCESS_SYSTEM_SECURITY;
        RequestedInfo |= SACL_SECURITY_INFORMATION;
    }

    dwFlags = 0;

    /* if we have the backup privilege, specify that */
    /* opening a directory requires FILE_FLAG_BACKUP_SEMANTICS */

    if(bBackupPrivilege || (VolumeCaps->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        dwFlags |= FILE_FLAG_BACKUP_SEMANTICS;

    hFile = CreateFileA(
        resource,
        dwDesiredAccess,
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, /* maximum sharing */
        NULL,
        OPEN_EXISTING,
        dwFlags,
        NULL
        );

    if(hFile == INVALID_HANDLE_VALUE) return FALSE;

    if(GetKernelObjectSecurity(hFile, RequestedInfo, sd, *cbBuffer, cbBuffer)) {
        *cbBuffer = GetSecurityDescriptorLength( sd );
        bSuccess = TRUE;
    }

    CloseHandle(hFile);

    return bSuccess;
}