mirror of
				https://github.com/tailscale/tailscale.git
				synced 2025-11-04 02:01:14 +01:00 
			
		
		
		
	Previously, tailscale upgrade was doing the bare minimum for checking authenticode signatures via `WinVerifyTrustEx`. This is fine, but we can do better: * WinVerifyTrustEx verifies that the binary's signature is valid, but it doesn't determine *whose* signature is valid; tailscale upgrade should also ensure that the binary is actually signed *by us*. * I added the ability to check the signatures of MSI files. * In future PRs I will be adding diagnostic logging that lists details about every module (ie, DLL) loaded into our process. As part of that metadata, I want to be able to extract information about who signed the binaries. This code is modelled on some C++ I wrote for Firefox back in the day. See https://searchfox.org/mozilla-central/rev/27e4816536c891d85d63695025f2549fd7976392/toolkit/xre/dllservices/mozglue/Authenticode.cpp for reference. Fixes #8284 Signed-off-by: Aaron Klotz <aaron@tailscale.com>
		
			
				
	
	
		
			136 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Code generated by 'go generate'; DO NOT EDIT.
 | 
						|
 | 
						|
package authenticode
 | 
						|
 | 
						|
import (
 | 
						|
	"syscall"
 | 
						|
	"unsafe"
 | 
						|
 | 
						|
	"github.com/dblohm7/wingoes"
 | 
						|
	"golang.org/x/sys/windows"
 | 
						|
)
 | 
						|
 | 
						|
var _ unsafe.Pointer
 | 
						|
 | 
						|
// Do the interface allocations only once for common
 | 
						|
// Errno values.
 | 
						|
const (
 | 
						|
	errnoERROR_IO_PENDING = 997
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
 | 
						|
	errERROR_EINVAL     error = syscall.EINVAL
 | 
						|
)
 | 
						|
 | 
						|
// errnoErr returns common boxed Errno values, to prevent
 | 
						|
// allocations at runtime.
 | 
						|
func errnoErr(e syscall.Errno) error {
 | 
						|
	switch e {
 | 
						|
	case 0:
 | 
						|
		return errERROR_EINVAL
 | 
						|
	case errnoERROR_IO_PENDING:
 | 
						|
		return errERROR_IO_PENDING
 | 
						|
	}
 | 
						|
	// TODO: add more here, after collecting data on the common
 | 
						|
	// error values see on Windows. (perhaps when running
 | 
						|
	// all.bat?)
 | 
						|
	return e
 | 
						|
}
 | 
						|
 | 
						|
var (
 | 
						|
	modcrypt32  = windows.NewLazySystemDLL("crypt32.dll")
 | 
						|
	modmsi      = windows.NewLazySystemDLL("msi.dll")
 | 
						|
	modwintrust = windows.NewLazySystemDLL("wintrust.dll")
 | 
						|
 | 
						|
	procCryptMsgClose                        = modcrypt32.NewProc("CryptMsgClose")
 | 
						|
	procCryptMsgGetParam                     = modcrypt32.NewProc("CryptMsgGetParam")
 | 
						|
	procCryptVerifyMessageSignature          = modcrypt32.NewProc("CryptVerifyMessageSignature")
 | 
						|
	procMsiGetFileSignatureInformationW      = modmsi.NewProc("MsiGetFileSignatureInformationW")
 | 
						|
	procCryptCATAdminAcquireContext2         = modwintrust.NewProc("CryptCATAdminAcquireContext2")
 | 
						|
	procCryptCATAdminCalcHashFromFileHandle2 = modwintrust.NewProc("CryptCATAdminCalcHashFromFileHandle2")
 | 
						|
	procCryptCATAdminEnumCatalogFromHash     = modwintrust.NewProc("CryptCATAdminEnumCatalogFromHash")
 | 
						|
	procCryptCATAdminReleaseCatalogContext   = modwintrust.NewProc("CryptCATAdminReleaseCatalogContext")
 | 
						|
	procCryptCATAdminReleaseContext          = modwintrust.NewProc("CryptCATAdminReleaseContext")
 | 
						|
	procCryptCATCatalogInfoFromContext       = modwintrust.NewProc("CryptCATCatalogInfoFromContext")
 | 
						|
)
 | 
						|
 | 
						|
func cryptMsgClose(cryptMsg windows.Handle) (err error) {
 | 
						|
	r1, _, e1 := syscall.Syscall(procCryptMsgClose.Addr(), 1, uintptr(cryptMsg), 0, 0)
 | 
						|
	if int32(r1) == 0 {
 | 
						|
		err = errnoErr(e1)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func cryptMsgGetParam(cryptMsg windows.Handle, paramType uint32, index uint32, data unsafe.Pointer, dataLen *uint32) (err error) {
 | 
						|
	r1, _, e1 := syscall.Syscall6(procCryptMsgGetParam.Addr(), 5, uintptr(cryptMsg), uintptr(paramType), uintptr(index), uintptr(data), uintptr(unsafe.Pointer(dataLen)), 0)
 | 
						|
	if int32(r1) == 0 {
 | 
						|
		err = errnoErr(e1)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func cryptVerifyMessageSignature(pVerifyPara *_CRYPT_VERIFY_MESSAGE_PARA, signerIndex uint32, pbSignedBlob *byte, cbSignedBlob uint32, pbDecoded *byte, pdbDecoded *uint32, ppSignerCert **windows.CertContext) (err error) {
 | 
						|
	r1, _, e1 := syscall.Syscall9(procCryptVerifyMessageSignature.Addr(), 7, uintptr(unsafe.Pointer(pVerifyPara)), uintptr(signerIndex), uintptr(unsafe.Pointer(pbSignedBlob)), uintptr(cbSignedBlob), uintptr(unsafe.Pointer(pbDecoded)), uintptr(unsafe.Pointer(pdbDecoded)), uintptr(unsafe.Pointer(ppSignerCert)), 0, 0)
 | 
						|
	if int32(r1) == 0 {
 | 
						|
		err = errnoErr(e1)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func msiGetFileSignatureInformation(signedObjectPath *uint16, flags uint32, certCtx **windows.CertContext, pbHashData *byte, cbHashData *uint32) (ret wingoes.HRESULT) {
 | 
						|
	r0, _, _ := syscall.Syscall6(procMsiGetFileSignatureInformationW.Addr(), 5, uintptr(unsafe.Pointer(signedObjectPath)), uintptr(flags), uintptr(unsafe.Pointer(certCtx)), uintptr(unsafe.Pointer(pbHashData)), uintptr(unsafe.Pointer(cbHashData)), 0)
 | 
						|
	ret = wingoes.HRESULT(r0)
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func cryptCATAdminAcquireContext2(hCatAdmin *_HCATADMIN, pgSubsystem *windows.GUID, hashAlgorithm *uint16, strongHashPolicy *windows.CertStrongSignPara, flags uint32) (err error) {
 | 
						|
	r1, _, e1 := syscall.Syscall6(procCryptCATAdminAcquireContext2.Addr(), 5, uintptr(unsafe.Pointer(hCatAdmin)), uintptr(unsafe.Pointer(pgSubsystem)), uintptr(unsafe.Pointer(hashAlgorithm)), uintptr(unsafe.Pointer(strongHashPolicy)), uintptr(flags), 0)
 | 
						|
	if int32(r1) == 0 {
 | 
						|
		err = errnoErr(e1)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func cryptCATAdminCalcHashFromFileHandle2(hCatAdmin _HCATADMIN, file windows.Handle, pcbHash *uint32, pbHash *byte, flags uint32) (err error) {
 | 
						|
	r1, _, e1 := syscall.Syscall6(procCryptCATAdminCalcHashFromFileHandle2.Addr(), 5, uintptr(hCatAdmin), uintptr(file), uintptr(unsafe.Pointer(pcbHash)), uintptr(unsafe.Pointer(pbHash)), uintptr(flags), 0)
 | 
						|
	if int32(r1) == 0 {
 | 
						|
		err = errnoErr(e1)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func cryptCATAdminEnumCatalogFromHash(hCatAdmin _HCATADMIN, pbHash *byte, cbHash uint32, flags uint32, prevCatInfo *_HCATINFO) (ret _HCATINFO, err error) {
 | 
						|
	r0, _, e1 := syscall.Syscall6(procCryptCATAdminEnumCatalogFromHash.Addr(), 5, uintptr(hCatAdmin), uintptr(unsafe.Pointer(pbHash)), uintptr(cbHash), uintptr(flags), uintptr(unsafe.Pointer(prevCatInfo)), 0)
 | 
						|
	ret = _HCATINFO(r0)
 | 
						|
	if ret == 0 {
 | 
						|
		err = errnoErr(e1)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func cryptCATAdminReleaseCatalogContext(hCatAdmin _HCATADMIN, hCatInfo _HCATINFO, flags uint32) (err error) {
 | 
						|
	r1, _, e1 := syscall.Syscall(procCryptCATAdminReleaseCatalogContext.Addr(), 3, uintptr(hCatAdmin), uintptr(hCatInfo), uintptr(flags))
 | 
						|
	if int32(r1) == 0 {
 | 
						|
		err = errnoErr(e1)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func cryptCATAdminReleaseContext(hCatAdmin _HCATADMIN, flags uint32) (err error) {
 | 
						|
	r1, _, e1 := syscall.Syscall(procCryptCATAdminReleaseContext.Addr(), 2, uintptr(hCatAdmin), uintptr(flags), 0)
 | 
						|
	if int32(r1) == 0 {
 | 
						|
		err = errnoErr(e1)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func cryptCATAdminCatalogInfoFromContext(hCatInfo _HCATINFO, catInfo *_CATALOG_INFO, flags uint32) (err error) {
 | 
						|
	r1, _, e1 := syscall.Syscall(procCryptCATCatalogInfoFromContext.Addr(), 3, uintptr(hCatInfo), uintptr(unsafe.Pointer(catInfo)), uintptr(flags))
 | 
						|
	if int32(r1) == 0 {
 | 
						|
		err = errnoErr(e1)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 |