返回 DeepSeek-Reasonix
authenticode_windows.go
根目录 / desktop / cmd / update-helper / authenticode_windows.go
1 //go:build windows
2
3 package main
4
5 import (
6 "fmt"
7 "io"
8 "os"
9 "unsafe"
10
11 "golang.org/x/sys/windows"
12 )
13
14 var readVerifiedWindowsStagedPayloadFn = readVerifiedWindowsStagedPayload
15
16 // readVerifiedWindowsStagedPayload verifies the Authenticode signature and
17 // reads the payload through one handle that disallows concurrent writes,
18 // deletes, and renames. The bytes handed to the publisher therefore cannot
19 // change between signature verification and publication.
20 func readVerifiedWindowsStagedPayload(path string) ([]byte, error) {
21 info, err := os.Lstat(path)
22 if err != nil {
23 return nil, err
24 }
25 if !info.Mode().IsRegular() {
26 return nil, fmt.Errorf("staged payload is not a regular file")
27 }
28 path16, err := windows.UTF16PtrFromString(path)
29 if err != nil {
30 return nil, err
31 }
32 handle, err := windows.CreateFile(
33 path16,
34 windows.GENERIC_READ,
35 windows.FILE_SHARE_READ,
36 nil,
37 windows.OPEN_EXISTING,
38 windows.FILE_ATTRIBUTE_NORMAL|windows.FILE_FLAG_SEQUENTIAL_SCAN,
39 0,
40 )
41 if err != nil {
42 return nil, err
43 }
44 file := os.NewFile(uintptr(handle), path)
45 if file == nil {
46 _ = windows.CloseHandle(handle)
47 return nil, fmt.Errorf("open staged payload handle")
48 }
49 defer file.Close()
50
51 fileInfo, err := file.Stat()
52 if err != nil {
53 return nil, err
54 }
55 if !fileInfo.Mode().IsRegular() {
56 return nil, fmt.Errorf("staged payload is not a regular file")
57 }
58
59 trustFile := &windows.WinTrustFileInfo{
60 Size: uint32(unsafe.Sizeof(windows.WinTrustFileInfo{})),
61 FilePath: path16,
62 File: handle,
63 }
64 trustData := &windows.WinTrustData{
65 Size: uint32(unsafe.Sizeof(windows.WinTrustData{})),
66 UIChoice: windows.WTD_UI_NONE,
67 RevocationChecks: windows.WTD_REVOKE_NONE,
68 UnionChoice: windows.WTD_CHOICE_FILE,
69 FileOrCatalogOrBlobOrSgnrOrCert: unsafe.Pointer(trustFile),
70 StateAction: windows.WTD_STATEACTION_VERIFY,
71 UIContext: windows.WTD_UICONTEXT_EXECUTE,
72 }
73 verifyErr := windows.WinVerifyTrustEx(
74 windows.InvalidHWND,
75 &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2,
76 trustData,
77 )
78 trustData.StateAction = windows.WTD_STATEACTION_CLOSE
79 closeErr := windows.WinVerifyTrustEx(
80 windows.InvalidHWND,
81 &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2,
82 trustData,
83 )
84 if verifyErr != nil {
85 if closeErr != nil {
86 return nil, fmt.Errorf("Authenticode verification failed: %v (release trust state: %w)", verifyErr, closeErr)
87 }
88 return nil, fmt.Errorf("Authenticode verification failed: %w", verifyErr)
89 }
90 if closeErr != nil {
91 return nil, fmt.Errorf("release Authenticode verification state: %w", closeErr)
92 }
93 if _, err := file.Seek(0, io.SeekStart); err != nil {
94 return nil, err
95 }
96 return io.ReadAll(file)
97 }
98
98 lines GO