aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-10-01 13:13:58 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-10-01 13:59:42 +0200
commite2adae0548c43213eae96fbf0fa90b8ad6d8d927 (patch)
treef8deaaa5431ddf6abd67255d509a67c8ddffd1e5
parentRevert "version: use crypt32 instead of go x509 for cn extraction for file size" (diff)
downloadwireguard-windows-e2adae0548c43213eae96fbf0fa90b8ad6d8d927.tar.xz
wireguard-windows-e2adae0548c43213eae96fbf0fa90b8ad6d8d927.zip
elevate: use fallback shellexecute when not EV-signed
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--elevate/shellexecute.go7
-rw-r--r--version/official_windows.go67
2 files changed, 73 insertions, 1 deletions
diff --git a/elevate/shellexecute.go b/elevate/shellexecute.go
index acb5b2e2..8e238f08 100644
--- a/elevate/shellexecute.go
+++ b/elevate/shellexecute.go
@@ -13,6 +13,8 @@ import (
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
+
+ "golang.zx2c4.com/wireguard/windows/version"
)
const (
@@ -45,6 +47,11 @@ func ShellExecute(program string, arguments string, directory string, show int32
}
}()
+ if !version.IsRunningEVSigned() {
+ err = windows.ERROR_INSUFFICIENT_LOGON_INFO
+ return
+ }
+
var processToken windows.Token
err = windows.OpenProcessToken(windows.CurrentProcess(), windows.TOKEN_QUERY|windows.TOKEN_DUPLICATE, &processToken)
if err != nil {
diff --git a/version/official_windows.go b/version/official_windows.go
index b0f62250..fffebe55 100644
--- a/version/official_windows.go
+++ b/version/official_windows.go
@@ -6,6 +6,7 @@
package version
import (
+ "encoding/asn1"
"os"
"unsafe"
@@ -15,8 +16,20 @@ import (
const (
officialCommonName = "WireGuard LLC"
+ evPolicyOid = "2.23.140.1.3"
+ policyExtensionOid = "2.5.29.32"
)
+type policyQualifierInfo struct {
+ PolicyQualifierId asn1.ObjectIdentifier
+ Qualifier asn1.RawValue
+}
+
+type policyInformation struct {
+ Policy asn1.ObjectIdentifier
+ Qualifiers []policyQualifierInfo `asn1:"optional"`
+}
+
func VerifyAuthenticode(path string) bool {
path16, err := windows.UTF16PtrFromString(path)
if err != nil {
@@ -65,7 +78,7 @@ func IsRunningOfficialVersion() bool {
return false
}
- // This below tests is easily circumvented. False certificates can be appended, and just checking the
+ // This below test is easily circumvented. False certificates can be appended, and just checking the
// common name is not very good. But that's okay, as this isn't security related.
certs, err := wintrust.ExtractCertificates(path)
if err != nil {
@@ -78,3 +91,55 @@ func IsRunningOfficialVersion() bool {
}
return false
}
+
+// This is an easily by-passable check, which doesn't serve a security purpose but mostly just a low-grade
+// informational and semantic one.
+func IsRunningEVSigned() bool {
+ path, err := os.Executable()
+ if err != nil {
+ return false
+ }
+ path16, err := windows.UTF16PtrFromString(path)
+ if err != nil {
+ return false
+ }
+ file := &wintrust.WinTrustFileInfo{
+ CbStruct: uint32(unsafe.Sizeof(wintrust.WinTrustFileInfo{})),
+ FilePath: path16,
+ }
+ data := &wintrust.WinTrustData{
+ CbStruct: uint32(unsafe.Sizeof(wintrust.WinTrustData{})),
+ UIChoice: wintrust.WTD_UI_NONE,
+ RevocationChecks: wintrust.WTD_REVOKE_NONE, // No revocation, as this isn't security related.
+ UnionChoice: wintrust.WTD_CHOICE_FILE,
+ StateAction: wintrust.WTD_STATEACTION_VERIFY,
+ FileOrCatalogOrBlobOrSgnrOrCert: uintptr(unsafe.Pointer(file)),
+ }
+ err = wintrust.WinVerifyTrust(0, &wintrust.WINTRUST_ACTION_GENERIC_VERIFY_V2, data)
+ if err != nil {
+ return false
+ }
+
+ // This below tests is easily circumvented. False certificates can be appended. But that's okay, as this isn't
+ // security related.
+ certs, err := wintrust.ExtractCertificates(path)
+ if err != nil {
+ return false
+ }
+ for _, cert := range certs {
+ for _, extension := range cert.Extensions {
+ if extension.Id.String() == policyExtensionOid {
+ var policies []policyInformation
+ if _, err = asn1.Unmarshal(extension.Value, &policies); err != nil {
+ continue
+ }
+ for _, policy := range policies {
+ if policy.Policy.String() == evPolicyOid {
+ return true
+ }
+ }
+ }
+ }
+ }
+ return false
+}