diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-11-21 14:59:03 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-11-22 22:00:32 +0100 |
commit | 259e2cb5eb2507d0321ceb9f46278df18ebe3066 (patch) | |
tree | 9f210d076e2768378b927440c67904c446d13f33 /conf/filewriter_windows.go | |
parent | manager: move IPC notification to go routine per client (diff) | |
download | wireguard-windows-259e2cb5eb2507d0321ceb9f46278df18ebe3066.tar.xz wireguard-windows-259e2cb5eb2507d0321ceb9f46278df18ebe3066.zip |
conf: allow administrators to add and remove configs easily
We loosen the permissions a little bit while tightening the
restrictions on encrypted files. This should allow administrators to
easily drop unencrypted files into Data\Configurations\ and get them
encrypted and made read-only, while also allowing them to delete
unwanted configurations.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
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 |