summary refs log tree commit diff stats
path: root/lib/pure/os.nim
diff options
context:
space:
mode:
authorRoman Inflianskas <rominf@users.noreply.github.com>2021-03-07 23:40:16 +0200
committerGitHub <noreply@github.com>2021-03-07 22:40:16 +0100
commit31424b380827b4da0bc08d1cb213dbad4288e30f (patch)
tree0e67d4e52fe122b56385b70b735e3c7e89278b59 /lib/pure/os.nim
parentd1e093207acdd10ad375705bd1732fc6f0db9f55 (diff)
downloadNim-31424b380827b4da0bc08d1cb213dbad4288e30f.tar.gz
stdlib/os: add isAdmin (#17012)
* stdlib/os: add isAdmin

* uint8 -> cuchar, assert isAdmin on Azure

Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>

* Update lib/pure/os.nim docs

Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>

* 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 <timothee.cour2@gmail.com>

Co-authored-by: Timothee Cour <timothee.cour2@gmail.com>
Diffstat (limited to 'lib/pure/os.nim')
-rw-r--r--lib/pure/os.nim30
1 files changed, 30 insertions, 0 deletions
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.