aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-08-28 21:50:19 -0600
committerJason A. Donenfeld <Jason@zx2c4.com>2019-08-30 08:47:21 -0600
commitff17660af8c4632271c2cac52c11887d08730d31 (patch)
tree7319c6c027134682e8c474bf9375a70d3aca8dde
parentmanager: fix nits in adapter cleanup logic and also handle ā€˜%sā€™ uniformly (diff)
downloadwireguard-windows-ff17660af8c4632271c2cac52c11887d08730d31.tar.xz
wireguard-windows-ff17660af8c4632271c2cac52c11887d08730d31.zip
elevate: use more strict check for admin group
-rw-r--r--elevate/membership.go33
-rw-r--r--elevate/shellexecute.go2
-rw-r--r--main.go2
-rw-r--r--manager/service.go2
4 files changed, 24 insertions, 15 deletions
diff --git a/elevate/membership.go b/elevate/membership.go
index baa4d71b..ccd0b60e 100644
--- a/elevate/membership.go
+++ b/elevate/membership.go
@@ -6,23 +6,32 @@
package elevate
import (
- "runtime"
-
"golang.org/x/sys/windows"
)
-func TokenIsMemberOfBuiltInAdministrator(token windows.Token) bool {
- gs, err := token.GetTokenGroups()
+func isAdmin(token windows.Token) bool {
+ builtinAdminsGroup, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid)
if err != nil {
return false
}
- isAdmin := false
- for _, g := range gs.AllGroups() {
- if (g.Attributes&windows.SE_GROUP_USE_FOR_DENY_ONLY != 0 || g.Attributes&windows.SE_GROUP_ENABLED != 0) && g.Sid.IsWellKnown(windows.WinBuiltinAdministratorsSid) {
- isAdmin = true
- break
- }
+ var checkableToken windows.Token
+ err = windows.DuplicateTokenEx(token, windows.TOKEN_QUERY | windows.TOKEN_IMPERSONATE, nil, windows.SecurityIdentification, windows.TokenImpersonation, &checkableToken)
+ if err != nil {
+ return false
+ }
+ defer checkableToken.Close()
+ isAdmin, err := checkableToken.IsMember(builtinAdminsGroup)
+ return isAdmin && err == nil
+}
+
+func TokenIsElevatedOrElevatable(token windows.Token) bool {
+ if token.IsElevated() && isAdmin(token) {
+ return true
+ }
+ linked, err := token.GetLinkedToken()
+ if err != nil {
+ return false
}
- runtime.KeepAlive(gs)
- return isAdmin
+ defer linked.Close()
+ return linked.IsElevated() && isAdmin(linked)
}
diff --git a/elevate/shellexecute.go b/elevate/shellexecute.go
index 6933c8f5..2c4190e0 100644
--- a/elevate/shellexecute.go
+++ b/elevate/shellexecute.go
@@ -54,7 +54,7 @@ func ShellExecute(program string, arguments string, directory string, show int32
err = windows.ERROR_SUCCESS
return
}
- if !TokenIsMemberOfBuiltInAdministrator(processToken) {
+ if !TokenIsElevatedOrElevatable(processToken) {
err = windows.ERROR_ACCESS_DENIED
return
}
diff --git a/main.go b/main.go
index bd86227e..e7070335 100644
--- a/main.go
+++ b/main.go
@@ -75,7 +75,7 @@ func checkForAdminGroup() {
fatal("Unable to open current process token: ", err)
}
defer processToken.Close()
- if !elevate.TokenIsMemberOfBuiltInAdministrator(processToken) {
+ if !elevate.TokenIsElevatedOrElevatable(processToken) {
fatal("WireGuard may only be used by users who are a member of the Builtin Administrators group.")
}
}
diff --git a/manager/service.go b/manager/service.go
index 8a525b12..43dd5d4c 100644
--- a/manager/service.go
+++ b/manager/service.go
@@ -104,7 +104,7 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
if err != nil {
return
}
- if !elevate.TokenIsMemberOfBuiltInAdministrator(userToken) {
+ if !elevate.TokenIsElevatedOrElevatable(userToken) {
userToken.Close()
return
}