mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-10-31 21:48:43 +00:00 
			
		
		
		
	 8d83adde07
			
		
	
	8d83adde07
	
	
	
		
			
			Package winenv provides information about the current Windows environment. This includes details such as whether the device is a server or workstation, and if it is AD domain-joined, MDM-registered, or neither. Updates tailscale/corp#18342 Signed-off-by: Nick Khyl <nickk@tailscale.com>
		
			
				
	
	
		
			110 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright (c) Tailscale Inc & AUTHORS
 | |
| // SPDX-License-Identifier: BSD-3-Clause
 | |
| 
 | |
| // Package winenv provides information about the current Windows environment.
 | |
| // This includes details such as whether the device is a server or workstation,
 | |
| // if it is AD domain-joined, MDM-registered, or neither, and other characteristics.
 | |
| package winenv
 | |
| 
 | |
| import (
 | |
| 	"runtime"
 | |
| 	"unsafe"
 | |
| 
 | |
| 	"golang.org/x/sys/windows"
 | |
| )
 | |
| 
 | |
| // osVersionInfoEx contains operating system version information.
 | |
| // See [OSVERSIONINFOEXW] for details.
 | |
| //
 | |
| // [OSVERSIONINFOEXW]: https://web.archive.org/web/20240407035213/https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-osversioninfoexw
 | |
| type osVersionInfoEx struct {
 | |
| 	cbSize           uint32
 | |
| 	majorVersion     uint32
 | |
| 	minorVersion     uint32
 | |
| 	buildNumber      uint32
 | |
| 	platformId       uint32
 | |
| 	csdVersion       [128]uint16
 | |
| 	servicePackMajor uint16
 | |
| 	servicePackMinor uint16
 | |
| 	suiteMask        uint16
 | |
| 	productType      verProductType
 | |
| 	reserved         uint8
 | |
| }
 | |
| 
 | |
| type (
 | |
| 	verTypeMask    uint32
 | |
| 	verCondMask    uint64
 | |
| 	verCond        uint8
 | |
| 	verProductType uint8
 | |
| )
 | |
| 
 | |
| // See [VER_SET_CONDITION] and [VerSetConditionMask] for details.
 | |
| //
 | |
| // [VER_SET_CONDITION]: https://web.archive.org/web/20240407035400/https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-ver_set_condition
 | |
| // [VerSetConditionMask]: https://web.archive.org/web/20240407035706/https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-versetconditionmask
 | |
| const (
 | |
| 	_VER_MINORVERSION     = verTypeMask(0x0000001)
 | |
| 	_VER_MAJORVERSION     = verTypeMask(0x0000002)
 | |
| 	_VER_BUILDNUMBER      = verTypeMask(0x0000004)
 | |
| 	_VER_PLATFORMID       = verTypeMask(0x0000008)
 | |
| 	_VER_SERVICEPACKMINOR = verTypeMask(0x0000010)
 | |
| 	_VER_SERVICEPACKMAJOR = verTypeMask(0x0000020)
 | |
| 	_VER_SUITENAME        = verTypeMask(0x0000040)
 | |
| 	_VER_PRODUCT_TYPE     = verTypeMask(0x0000080)
 | |
| 
 | |
| 	_VER_NT_WORKSTATION       = verProductType(1)
 | |
| 	_VER_NT_DOMAIN_CONTROLLER = verProductType(2)
 | |
| 	_VER_NT_SERVER            = verProductType(3)
 | |
| 
 | |
| 	_VER_EQUAL         = verCond(1)
 | |
| 	_VER_GREATER       = verCond(2)
 | |
| 	_VER_GREATER_EQUAL = verCond(3)
 | |
| 	_VER_LESS          = verCond(4)
 | |
| 	_VER_LESS_EQUAL    = verCond(5)
 | |
| 	_VER_AND           = verCond(6)
 | |
| 	_VER_OR            = verCond(7)
 | |
| )
 | |
| 
 | |
| // IsDomainJoined reports whether the device is domain-joined.
 | |
| func IsDomainJoined() bool {
 | |
| 	var domain *uint16
 | |
| 	var status uint32
 | |
| 	if err := windows.NetGetJoinInformation(nil, &domain, &status); err != nil {
 | |
| 		return false
 | |
| 	}
 | |
| 	windows.NetApiBufferFree((*byte)(unsafe.Pointer(domain)))
 | |
| 	return status == windows.NetSetupDomainName
 | |
| }
 | |
| 
 | |
| // IsMDMRegistered reports whether the device is MDM-registered.
 | |
| func IsMDMRegistered() bool {
 | |
| 	const S_OK int32 = 0
 | |
| 	var isMDMRegistered bool
 | |
| 	if hr, err := isDeviceRegisteredWithManagement(&isMDMRegistered, 0, nil); err != nil || hr != S_OK {
 | |
| 		return false
 | |
| 	}
 | |
| 	return isMDMRegistered
 | |
| }
 | |
| 
 | |
| // IsManaged reports whether the device is managed through AD or MDM.
 | |
| func IsManaged() bool {
 | |
| 	return IsDomainJoined() || IsMDMRegistered()
 | |
| }
 | |
| 
 | |
| // IsWindowsServer reports whether the device is running a Windows Server operating system.
 | |
| func IsWindowsServer() bool {
 | |
| 	if runtime.GOARCH != "amd64" && runtime.GOARCH != "arm64" {
 | |
| 		// TODO(nickkhyl): the Windows Server versions we support do not have 32-bit editions.
 | |
| 		// But we should remove this check once we adopt mkwinsyscallx, as it can handle 64-bit
 | |
| 		// long arguments such as verCondMask.
 | |
| 		return false
 | |
| 	}
 | |
| 
 | |
| 	osvi := &osVersionInfoEx{
 | |
| 		cbSize:      uint32(unsafe.Sizeof(osVersionInfoEx{})),
 | |
| 		productType: _VER_NT_WORKSTATION,
 | |
| 	}
 | |
| 	condMask := verSetConditionMask(0, _VER_PRODUCT_TYPE, _VER_EQUAL)
 | |
| 	return !verifyVersionInfo(osvi, _VER_PRODUCT_TYPE, condMask)
 | |
| }
 |