mirror of
https://github.com/status-im/nim-stew.git
synced 2025-01-09 11:45:42 +00:00
Fix inherited objects problem. (#59)
This commit is contained in:
parent
7018fb0b5e
commit
bc3b4cf2de
@ -28,8 +28,11 @@ const
|
|||||||
PROTECTED_DACL_SECURITY_INFORMATION = 0x8000_0000'u32
|
PROTECTED_DACL_SECURITY_INFORMATION = 0x8000_0000'u32
|
||||||
SE_FILE_OBJECT = 0x0000_0001'u32
|
SE_FILE_OBJECT = 0x0000_0001'u32
|
||||||
ERROR_SUCCESS = 0x0000_0000'u32
|
ERROR_SUCCESS = 0x0000_0000'u32
|
||||||
|
ERROR_PATH_NOT_FOUND = 0x0000_0003'u32
|
||||||
SECURITY_DESCRIPTOR_MIN_LENGTH = 40
|
SECURITY_DESCRIPTOR_MIN_LENGTH = 40
|
||||||
SECURITY_DESCRIPTOR_REVISION = 1'u32
|
SECURITY_DESCRIPTOR_REVISION = 1'u32
|
||||||
|
ACCESS_ALLOWED_ACE_TYPE = 0x00'u8
|
||||||
|
SE_DACL_PROTECTED = 0x1000'u16
|
||||||
|
|
||||||
type
|
type
|
||||||
ACL {.pure, final.} = object
|
ACL {.pure, final.} = object
|
||||||
@ -65,6 +68,9 @@ type
|
|||||||
mask: uint32
|
mask: uint32
|
||||||
sidStart: uint32
|
sidStart: uint32
|
||||||
|
|
||||||
|
SecDescriptorKind = enum
|
||||||
|
File, Folder
|
||||||
|
|
||||||
proc closeHandle(hobj: uint): int32 {.
|
proc closeHandle(hobj: uint): int32 {.
|
||||||
importc: "CloseHandle", dynlib: "kernel32", stdcall, sideEffect.}
|
importc: "CloseHandle", dynlib: "kernel32", stdcall, sideEffect.}
|
||||||
proc localFree(p: pointer): uint {.
|
proc localFree(p: pointer): uint {.
|
||||||
@ -117,6 +123,10 @@ proc addAccessAllowedAceEx(pAcl: PACL, dwAceRevision: uint32,
|
|||||||
sideEffect.}
|
sideEffect.}
|
||||||
proc getAce(pAcl: PACL, dwAceIndex: uint32, pAce: pointer): int32 {.
|
proc getAce(pAcl: PACL, dwAceIndex: uint32, pAce: pointer): int32 {.
|
||||||
importc: "GetAce", dynlib: "advapi32", stdcall, sideEffect.}
|
importc: "GetAce", dynlib: "advapi32", stdcall, sideEffect.}
|
||||||
|
proc setSecurityDescriptorControl(pSD: pointer, bitsOfInterest: uint16,
|
||||||
|
bitsToSet: uint16): int32 {.
|
||||||
|
importc: "SetSecurityDescriptorControl", dynlib: "advapi32", stdcall,
|
||||||
|
sideEffect.}
|
||||||
|
|
||||||
proc len*(sid: SID): int = len(sid.data)
|
proc len*(sid: SID): int = len(sid.data)
|
||||||
|
|
||||||
@ -181,7 +191,7 @@ template getAddr*(sid: SID): pointer =
|
|||||||
## Obtain Windows specific SID pointer.
|
## Obtain Windows specific SID pointer.
|
||||||
unsafeAddr sid.data[0]
|
unsafeAddr sid.data[0]
|
||||||
|
|
||||||
proc createCurrentUserOnlyAcl(): IoResult[seq[byte]] =
|
proc createCurrentUserOnlyAcl(kind: SecDescriptorKind): IoResult[seq[byte]] =
|
||||||
let aceMask = FILE_ALL_ACCESS
|
let aceMask = FILE_ALL_ACCESS
|
||||||
var userSid = ? getCurrentUserSid()
|
var userSid = ? getCurrentUserSid()
|
||||||
let size =
|
let size =
|
||||||
@ -193,7 +203,11 @@ proc createCurrentUserOnlyAcl(): IoResult[seq[byte]] =
|
|||||||
if initializeAcl(pdacl, uint32(size), ACL_REVISION) == 0:
|
if initializeAcl(pdacl, uint32(size), ACL_REVISION) == 0:
|
||||||
err(ioLastError())
|
err(ioLastError())
|
||||||
else:
|
else:
|
||||||
let aceFlags = OBJECT_INHERIT_ACE or CONTAINER_INHERIT_ACE
|
let aceFlags =
|
||||||
|
if kind == Folder:
|
||||||
|
OBJECT_INHERIT_ACE or CONTAINER_INHERIT_ACE
|
||||||
|
else:
|
||||||
|
0'u32
|
||||||
if addAccessAllowedAceEx(pdacl, ACL_REVISION, aceFlags,
|
if addAccessAllowedAceEx(pdacl, ACL_REVISION, aceFlags,
|
||||||
aceMask, userSid.getAddr()) == 0:
|
aceMask, userSid.getAddr()) == 0:
|
||||||
err(ioLastError())
|
err(ioLastError())
|
||||||
@ -204,7 +218,16 @@ proc setCurrentUserOnlyAccess*(path: string): IoResult[void] =
|
|||||||
## Set file or folder with path ``path`` to be accessed only by current
|
## Set file or folder with path ``path`` to be accessed only by current
|
||||||
## process' user. All other user's and user's group access will be
|
## process' user. All other user's and user's group access will be
|
||||||
## prohibited.
|
## prohibited.
|
||||||
var buffer = ? createCurrentUserOnlyAcl()
|
if not(fileAccessible(path, {})):
|
||||||
|
return err(IoErrorCode(ERROR_PATH_NOT_FOUND))
|
||||||
|
|
||||||
|
let descriptorKind =
|
||||||
|
if isDir(path):
|
||||||
|
Folder
|
||||||
|
else:
|
||||||
|
File
|
||||||
|
|
||||||
|
var buffer = ? createCurrentUserOnlyAcl(descriptorKind)
|
||||||
var pdacl = cast[PACL](addr buffer[0])
|
var pdacl = cast[PACL](addr buffer[0])
|
||||||
|
|
||||||
let dflags = DACL_SECURITY_INFORMATION or
|
let dflags = DACL_SECURITY_INFORMATION or
|
||||||
@ -216,22 +239,34 @@ proc setCurrentUserOnlyAccess*(path: string): IoResult[void] =
|
|||||||
else:
|
else:
|
||||||
ok()
|
ok()
|
||||||
|
|
||||||
proc createCurrentUserOnlySecurityDescriptor*(): IoResult[SD] =
|
proc createUserOnlySecurityDescriptor(kind: SecDescriptorKind): IoResult[SD] =
|
||||||
## Create security descriptor which can be used to limit access to resource
|
var dacl = ? createCurrentUserOnlyAcl(kind)
|
||||||
## to current process user.
|
|
||||||
var dacl = ? createCurrentUserOnlyAcl()
|
|
||||||
var buffer = newSeq[byte](SECURITY_DESCRIPTOR_MIN_LENGTH)
|
var buffer = newSeq[byte](SECURITY_DESCRIPTOR_MIN_LENGTH)
|
||||||
if initializeSecurityDescriptor(addr buffer[0],
|
if initializeSecurityDescriptor(addr buffer[0],
|
||||||
SECURITY_DESCRIPTOR_REVISION) == 0:
|
SECURITY_DESCRIPTOR_REVISION) == 0:
|
||||||
err(ioLastError())
|
err(ioLastError())
|
||||||
else:
|
else:
|
||||||
var res = SD(sddata: buffer, acldata: dacl)
|
var res = SD(sddata: buffer, acldata: dacl)
|
||||||
|
let bits = SE_DACL_PROTECTED
|
||||||
|
if setSecurityDescriptorControl(addr res.sddata[0], bits, bits) == 0:
|
||||||
|
err(ioLastError())
|
||||||
|
else:
|
||||||
if setSecurityDescriptorDacl(addr res.sddata[0], 1'i32,
|
if setSecurityDescriptorDacl(addr res.sddata[0], 1'i32,
|
||||||
addr res.acldata[0], 0'i32) == 0:
|
addr res.acldata[0], 0'i32) == 0:
|
||||||
err(ioLastError())
|
err(ioLastError())
|
||||||
else:
|
else:
|
||||||
ok(res)
|
ok(res)
|
||||||
|
|
||||||
|
proc createFoldersUserOnlySecurityDescriptor*(): IoResult[SD] {.inline.} =
|
||||||
|
## Create security descriptor which can be used to restrict folder access to
|
||||||
|
## only the current process user.
|
||||||
|
createUserOnlySecurityDescriptor(Folder)
|
||||||
|
|
||||||
|
proc createFilesUserOnlySecurityDescriptor*(): IoResult[SD] {.inline.} =
|
||||||
|
## Create security descriptor which can be used to restrict file access to
|
||||||
|
## only the current process user.
|
||||||
|
createUserOnlySecurityDescriptor(File)
|
||||||
|
|
||||||
proc isEmpty*(sd: SD): bool =
|
proc isEmpty*(sd: SD): bool =
|
||||||
## Returns ``true`` is security descriptor ``sd`` is not initialized.
|
## Returns ``true`` is security descriptor ``sd`` is not initialized.
|
||||||
(len(sd.sddata) == 0) or (len(sd.acldata) == 0)
|
(len(sd.sddata) == 0) or (len(sd.acldata) == 0)
|
||||||
@ -247,7 +282,6 @@ proc checkCurrentUserOnlyACL*(path: string): IoResult[bool] =
|
|||||||
sdesc: pointer
|
sdesc: pointer
|
||||||
pdacl: PACL
|
pdacl: PACL
|
||||||
|
|
||||||
let aceFlags = OBJECT_INHERIT_ACE or CONTAINER_INHERIT_ACE
|
|
||||||
let userSid = ? getCurrentUserSid()
|
let userSid = ? getCurrentUserSid()
|
||||||
let gres = getNamedSecurityInfo(newWideCString(path), SE_FILE_OBJECT,
|
let gres = getNamedSecurityInfo(newWideCString(path), SE_FILE_OBJECT,
|
||||||
DACL_SECURITY_INFORMATION, nil, nil,
|
DACL_SECURITY_INFORMATION, nil, nil,
|
||||||
@ -273,10 +307,17 @@ proc checkCurrentUserOnlyACL*(path: string): IoResult[bool] =
|
|||||||
discard localFree(sdesc)
|
discard localFree(sdesc)
|
||||||
err(errCode)
|
err(errCode)
|
||||||
else:
|
else:
|
||||||
|
let expectedFlags =
|
||||||
|
if isDir(path):
|
||||||
|
OBJECT_INHERIT_ACE or CONTAINER_INHERIT_ACE
|
||||||
|
else:
|
||||||
|
0x00'u32
|
||||||
|
|
||||||
var psid = cast[pointer](addr ace.sidStart)
|
var psid = cast[pointer](addr ace.sidStart)
|
||||||
if isValidSid(psid) != 0:
|
if isValidSid(psid) != 0:
|
||||||
if equalSid(psid, userSid.getAddr()) != 0:
|
if equalSid(psid, userSid.getAddr()) != 0:
|
||||||
if ace[].header.aceFlags == aceFlags and
|
if ace[].header.aceType == ACCESS_ALLOWED_ACE_TYPE and
|
||||||
|
ace[].header.aceFlags == expectedFlags and
|
||||||
ace[].mask == FILE_ALL_ACCESS:
|
ace[].mask == FILE_ALL_ACCESS:
|
||||||
ok(true)
|
ok(true)
|
||||||
else:
|
else:
|
||||||
|
@ -8,16 +8,27 @@ suite "Windows security descriptor tests suite":
|
|||||||
test "File/Folder user-only ACL create/verify test":
|
test "File/Folder user-only ACL create/verify test":
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
proc performTest(path1: string, path2: string): IoResult[bool] =
|
proc performTest(path1: string, path2: string): IoResult[bool] =
|
||||||
var sd = ? createCurrentUserOnlySecurityDescriptor()
|
let path3 = path1 & "\\" & path1
|
||||||
|
let path4 = path1 & "\\" & path2
|
||||||
|
var sdd = ? createFoldersUserOnlySecurityDescriptor()
|
||||||
|
var sdf = ? createFilesUserOnlySecurityDescriptor()
|
||||||
# Create directory
|
# Create directory
|
||||||
? createPath(path1, secDescriptor = sd.getDescriptor())
|
? createPath(path1, secDescriptor = sdd.getDescriptor())
|
||||||
# Create file
|
# Create file outside of directory
|
||||||
? writeFile(path2, "TESTBLOB", secDescriptor = sd.getDescriptor())
|
? writeFile(path2, "TESTBLOB", secDescriptor = sdf.getDescriptor())
|
||||||
|
# Create directory inside of directory
|
||||||
|
? createPath(path3, secDescriptor = sdd.getDescriptor())
|
||||||
|
# Create file inside of directory
|
||||||
|
? writeFile(path4, "TESTLBOB", secDescriptor = sdf.getDescriptor())
|
||||||
let res1 = ? checkCurrentUserOnlyACL(path1)
|
let res1 = ? checkCurrentUserOnlyACL(path1)
|
||||||
let res2 = ? checkCurrentUserOnlyACL(path2)
|
let res2 = ? checkCurrentUserOnlyACL(path2)
|
||||||
|
let res3 = ? checkCurrentUserOnlyACL(path3)
|
||||||
|
let res4 = ? checkCurrentUserOnlyACL(path4)
|
||||||
|
? removeFile(path4)
|
||||||
|
? removeDir(path3)
|
||||||
? removeFile(path2)
|
? removeFile(path2)
|
||||||
? removeDir(path1)
|
? removeDir(path1)
|
||||||
if res1 and res2:
|
if res1 and res2 and res3 and res4:
|
||||||
ok(true)
|
ok(true)
|
||||||
else:
|
else:
|
||||||
err(IoErrorCode(UserErrorCode))
|
err(IoErrorCode(UserErrorCode))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user