From 31424b380827b4da0bc08d1cb213dbad4288e30f Mon Sep 17 00:00:00 2001 From: Roman Inflianskas Date: Sun, 7 Mar 2021 23:40:16 +0200 Subject: stdlib/os: add isAdmin (#17012) * stdlib/os: add isAdmin * uint8 -> cuchar, assert isAdmin on Azure Co-authored-by: Timothee Cour * Update lib/pure/os.nim docs Co-authored-by: Timothee Cour * Address comments on #17012 * Raise on errors in #17012 * Check the result of FreeSid in #17012 * Change case in #17012 * Fix memory leak in #17012 * Address comments in #17012 Co-authored-by: Timothee Cour Co-authored-by: Timothee Cour --- lib/pure/os.nim | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'lib/pure/os.nim') diff --git a/lib/pure/os.nim b/lib/pure/os.nim index b900546a0..df9a1180c 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1688,6 +1688,36 @@ proc setFilePermissions*(filename: string, permissions: set[FilePermission], var res2 = setFileAttributesA(filename, res) if res2 == - 1'i32: raiseOSError(osLastError(), $(filename, permissions)) +proc isAdmin*: bool {.noWeirdTarget.} = + ## Returns whether the caller's process is a member of the Administrators local + ## group (on Windows) or a root (on POSIX), via `geteuid() == 0`. + when defined(windows): + # Rewrite of the example from Microsoft Docs: + # https://docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/nf-securitybaseapi-checktokenmembership#examples + # and corresponding PostgreSQL function: + # https://doxygen.postgresql.org/win32security_8c.html#ae6b61e106fa5d6c5d077a9d14ee80569 + var ntAuthority = SID_IDENTIFIER_AUTHORITY(value: SECURITY_NT_AUTHORITY) + var administratorsGroup: PSID + if not isSuccess(allocateAndInitializeSid(addr ntAuthority, + BYTE(2), + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + addr administratorsGroup)): + raiseOSError(osLastError(), "could not get SID for Administrators group") + + defer: + if freeSid(administratorsGroup) != nil: + raiseOSError(osLastError(), "failed to free SID for Administrators group") + + var b: WINBOOL + if not isSuccess(checkTokenMembership(0, administratorsGroup, addr b)): + raiseOSError(osLastError(), "could not check access token membership") + + return isSuccess(b) + else: + return geteuid() == 0 + proc createSymlink*(src, dest: string) {.noWeirdTarget.} = ## Create a symbolic link at `dest` which points to the item specified ## by `src`. On most operating systems, will fail if a link already exists. -- cgit 1.4.1-2-gfad0