From 7a47c044cebd04bdedc8e04c2b99813357daffcc Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 13 Jun 2019 16:27:28 +0200 Subject: conf: separate out migration --- conf/migration_windows.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++ conf/mksyscall.go | 2 +- conf/path_windows.go | 52 -------------------------------------- 3 files changed, 65 insertions(+), 53 deletions(-) create mode 100644 conf/migration_windows.go diff --git a/conf/migration_windows.go b/conf/migration_windows.go new file mode 100644 index 00000000..ad7c1778 --- /dev/null +++ b/conf/migration_windows.go @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2019 WireGuard LLC. All Rights Reserved. + */ + +package conf + +import ( + "log" + "path/filepath" + "strings" + + "golang.org/x/sys/windows" +) + +//sys getFileSecurity(fileName *uint16, securityInformation uint32, securityDescriptor *byte, descriptorLen uint32, requestedLen *uint32) (err error) = advapi32.GetFileSecurityW +//sys getSecurityDescriptorOwner(securityDescriptor *byte, sid **windows.SID, ownerDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorOwner +const ownerSecurityInformation = 0x00000001 + +func maybeMigrate(c string) { + vol := filepath.VolumeName(c) + withoutVol := strings.TrimPrefix(c, vol) + oldRoot := filepath.Join(vol, "\\windows.old") + oldC := filepath.Join(oldRoot, withoutVol) + + var err error + var sd []byte + reqLen := uint32(128) + for { + sd = make([]byte, reqLen) + //XXX: Since this takes a file path, it's technically a TOCTOU. + err = getFileSecurity(windows.StringToUTF16Ptr(oldRoot), ownerSecurityInformation, &sd[0], uint32(len(sd)), &reqLen) + if err != windows.ERROR_INSUFFICIENT_BUFFER { + break + } + } + if err == windows.ERROR_PATH_NOT_FOUND { + return + } + if err != nil { + log.Printf("Not migrating configuration from '%s' due to GetFileSecurity error: %v", oldRoot, err) + return + } + var defaulted bool + var sid *windows.SID + err = getSecurityDescriptorOwner(&sd[0], &sid, &defaulted) + if err != nil { + log.Printf("Not migrating configuration from '%s' due to GetSecurityDescriptorOwner error: %v", oldRoot, err) + return + } + if defaulted || !sid.IsWellKnown(windows.WinLocalSystemSid) { + sidStr, _ := sid.String() + log.Printf("Not migrating configuration from '%s', as it is not explicitly owned by SYSTEM, but rather '%s'", oldRoot, sidStr) + return + } + err = windows.MoveFileEx(windows.StringToUTF16Ptr(oldC), windows.StringToUTF16Ptr(c), windows.MOVEFILE_COPY_ALLOWED) + if err != nil { + if err != windows.ERROR_FILE_NOT_FOUND && err != windows.ERROR_ALREADY_EXISTS { + log.Printf("Not migrating configuration from '%s' due to error when moving files: %v", oldRoot, err) + } + return + } + log.Printf("Migrated configuration from '%s'", oldRoot) +} diff --git a/conf/mksyscall.go b/conf/mksyscall.go index b5c4857f..0cb6d609 100644 --- a/conf/mksyscall.go +++ b/conf/mksyscall.go @@ -5,4 +5,4 @@ package conf -//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go dnsresolver_windows.go path_windows.go storewatcher_windows.go +//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go dnsresolver_windows.go migration_windows.go storewatcher_windows.go diff --git a/conf/path_windows.go b/conf/path_windows.go index 8da97708..3d0f2504 100644 --- a/conf/path_windows.go +++ b/conf/path_windows.go @@ -6,67 +6,15 @@ package conf import ( - "log" "os" "path/filepath" - "strings" "golang.org/x/sys/windows" ) -//sys getFileSecurity(fileName *uint16, securityInformation uint32, securityDescriptor *byte, descriptorLen uint32, requestedLen *uint32) (err error) = advapi32.GetFileSecurityW -//sys getSecurityDescriptorOwner(securityDescriptor *byte, sid **windows.SID, ownerDefaulted *bool) (err error) = advapi32.GetSecurityDescriptorOwner -const ownerSecurityInformation = 0x00000001 - var cachedConfigFileDir string var cachedRootDir string -func maybeMigrate(c string) { - vol := filepath.VolumeName(c) - withoutVol := strings.TrimPrefix(c, vol) - oldRoot := filepath.Join(vol, "\\windows.old") - oldC := filepath.Join(oldRoot, withoutVol) - - var err error - var sd []byte - reqLen := uint32(128) - for { - sd = make([]byte, reqLen) - //XXX: Since this takes a file path, it's technically a TOCTOU. - err = getFileSecurity(windows.StringToUTF16Ptr(oldRoot), ownerSecurityInformation, &sd[0], uint32(len(sd)), &reqLen) - if err != windows.ERROR_INSUFFICIENT_BUFFER { - break - } - } - if err == windows.ERROR_PATH_NOT_FOUND { - return - } - if err != nil { - log.Printf("Not migrating configuration from '%s' due to GetFileSecurity error: %v", oldRoot, err) - return - } - var defaulted bool - var sid *windows.SID - err = getSecurityDescriptorOwner(&sd[0], &sid, &defaulted) - if err != nil { - log.Printf("Not migrating configuration from '%s' due to GetSecurityDescriptorOwner error: %v", oldRoot, err) - return - } - if defaulted || !sid.IsWellKnown(windows.WinLocalSystemSid) { - sidStr, _ := sid.String() - log.Printf("Not migrating configuration from '%s', as it is not explicitly owned by SYSTEM, but rather '%s'", oldRoot, sidStr) - return - } - err = windows.MoveFileEx(windows.StringToUTF16Ptr(oldC), windows.StringToUTF16Ptr(c), windows.MOVEFILE_COPY_ALLOWED) - if err != nil { - if err != windows.ERROR_FILE_NOT_FOUND && err != windows.ERROR_ALREADY_EXISTS { - log.Printf("Not migrating configuration from '%s' due to error when moving files: %v", oldRoot, err) - } - return - } - log.Printf("Migrated configuration from '%s'", oldRoot) -} - func tunnelConfigurationsDirectory() (string, error) { if cachedConfigFileDir != "" { return cachedConfigFileDir, nil -- cgit v1.2.3-59-g8ed1b