diff options
Diffstat (limited to 'conf/filewriter_windows.go')
-rw-r--r-- | conf/filewriter_windows.go | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/conf/filewriter_windows.go b/conf/filewriter_windows.go new file mode 100644 index 00000000..9fb1f566 --- /dev/null +++ b/conf/filewriter_windows.go @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2020 WireGuard LLC. All Rights Reserved. + */ + +package conf + +import ( + "sync/atomic" + "unsafe" + + "golang.org/x/sys/windows" +) + +var encryptedFileSd unsafe.Pointer + +func writeEncryptedFile(destination string, contents []byte) error { + var err error + sa := &windows.SecurityAttributes{Length: uint32(unsafe.Sizeof(windows.SecurityAttributes{}))} + sa.SecurityDescriptor = (*windows.SECURITY_DESCRIPTOR)(atomic.LoadPointer(&encryptedFileSd)) + if sa.SecurityDescriptor == nil { + sa.SecurityDescriptor, err = windows.SecurityDescriptorFromString("O:SYG:SYD:PAI(A;;FA;;;SY)(A;;SD;;;BA)") + if err != nil { + return err + } + atomic.StorePointer(&encryptedFileSd, unsafe.Pointer(sa.SecurityDescriptor)) + } + destination16, err := windows.UTF16FromString(destination) + if err != nil { + return err + } + tmpDestination := destination + ".tmp" + tmpDestination16, err := windows.UTF16PtrFromString(tmpDestination) + if err != nil { + return err + } + handle, err := windows.CreateFile(tmpDestination16, windows.GENERIC_WRITE|windows.DELETE, 0, sa, windows.CREATE_ALWAYS, windows.FILE_ATTRIBUTE_NORMAL, 0) + if err != nil { + return err + } + defer windows.CloseHandle(handle) + deleteIt := func() { + yes := byte(1) + windows.SetFileInformationByHandle(handle, windows.FileDispositionInfo, &yes, 1) + } + n, err := windows.Write(handle, contents) + if err != nil { + deleteIt() + return err + } + if n != len(contents) { + deleteIt() + return windows.ERROR_IO_INCOMPLETE + } + fileRenameInfo := &struct { + replaceIfExists byte + rootDirectory windows.Handle + fileNameLength uint32 + fileName [windows.MAX_PATH]uint16 + }{replaceIfExists: 1, fileNameLength: uint32(len(destination16) - 1)} + if len(destination16) > len(fileRenameInfo.fileName) { + deleteIt() + return windows.ERROR_BUFFER_OVERFLOW + } + copy(fileRenameInfo.fileName[:], destination16[:]) + err = windows.SetFileInformationByHandle(handle, windows.FileRenameInfo, (*byte)(unsafe.Pointer(fileRenameInfo)), uint32(unsafe.Sizeof(*fileRenameInfo))) + if err != nil { + deleteIt() + return err + } + return nil +}
\ No newline at end of file |