mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-08-10 13:20:33 +02:00
cmd/cli: make --cleanup removing more files
While at it, also implementing self-delete function for Windows.
This commit is contained in:
+23
-1
@@ -48,6 +48,7 @@ import (
|
|||||||
|
|
||||||
// selfCheckInternalTestDomain is used for testing ctrld self response to clients.
|
// selfCheckInternalTestDomain is used for testing ctrld self response to clients.
|
||||||
const selfCheckInternalTestDomain = "ctrld" + loopTestDomain
|
const selfCheckInternalTestDomain = "ctrld" + loopTestDomain
|
||||||
|
const windowsForwardersFilename = ".forwarders.txt"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
version = "dev"
|
version = "dev"
|
||||||
@@ -610,8 +611,22 @@ NOTE: Uninstalling will set DNS to values provided by DHCP.`,
|
|||||||
files = append(files, filepath.Join(dir, ctrldControlUnixSock))
|
files = append(files, filepath.Join(dir, ctrldControlUnixSock))
|
||||||
files = append(files, filepath.Join(dir, ctrldLogUnixSock))
|
files = append(files, filepath.Join(dir, ctrldLogUnixSock))
|
||||||
}
|
}
|
||||||
|
// Static DNS settings files.
|
||||||
|
withEachPhysicalInterfaces("", "", func(i *net.Interface) error {
|
||||||
|
file := savedStaticDnsSettingsFilePath(i)
|
||||||
|
if _, err := os.Stat(file); err == nil {
|
||||||
|
files = append(files, file)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
// Windows forwarders file.
|
||||||
|
if windowsHasLocalDnsServerRunning() {
|
||||||
|
files = append(files, absHomeDir(windowsForwardersFilename))
|
||||||
|
}
|
||||||
// Binary itself.
|
// Binary itself.
|
||||||
if bin, _ := os.Executable(); bin != "" {
|
|
||||||
|
bin, _ := os.Executable()
|
||||||
|
if bin != "" && supportedSelfDelete {
|
||||||
files = append(files, bin)
|
files = append(files, bin)
|
||||||
}
|
}
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
@@ -627,6 +642,13 @@ NOTE: Uninstalling will set DNS to values provided by DHCP.`,
|
|||||||
mainLog.Load().Debug().Msgf("file removed: %s", file)
|
mainLog.Load().Debug().Msgf("file removed: %s", file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := selfDeleteExe(); err != nil {
|
||||||
|
mainLog.Load().Warn().Err(err).Msg("failed to remove file")
|
||||||
|
} else {
|
||||||
|
if !supportedSelfDelete {
|
||||||
|
mainLog.Load().Debug().Msgf("file removed: %s", bin)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
forwardersFilename = ".forwarders.txt"
|
|
||||||
v4InterfaceKeyPathFormat = `HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\`
|
v4InterfaceKeyPathFormat = `HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\`
|
||||||
v6InterfaceKeyPathFormat = `HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters\Interfaces\`
|
v6InterfaceKeyPathFormat = `HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters\Interfaces\`
|
||||||
)
|
)
|
||||||
@@ -40,7 +39,7 @@ func setDNS(iface *net.Interface, nameservers []string) error {
|
|||||||
// If there's a Dns server running, that means we are on AD with Dns feature enabled.
|
// If there's a Dns server running, that means we are on AD with Dns feature enabled.
|
||||||
// Configuring the Dns server to forward queries to ctrld instead.
|
// Configuring the Dns server to forward queries to ctrld instead.
|
||||||
if windowsHasLocalDnsServerRunning() {
|
if windowsHasLocalDnsServerRunning() {
|
||||||
file := absHomeDir(forwardersFilename)
|
file := absHomeDir(windowsForwardersFilename)
|
||||||
oldForwardersContent, _ := os.ReadFile(file)
|
oldForwardersContent, _ := os.ReadFile(file)
|
||||||
if err := os.WriteFile(file, []byte(strings.Join(nameservers, ",")), 0600); err != nil {
|
if err := os.WriteFile(file, []byte(strings.Join(nameservers, ",")), 0600); err != nil {
|
||||||
mainLog.Load().Warn().Err(err).Msg("could not save forwarders settings")
|
mainLog.Load().Warn().Err(err).Msg("could not save forwarders settings")
|
||||||
@@ -72,7 +71,7 @@ func resetDNS(iface *net.Interface) error {
|
|||||||
resetDNSOnce.Do(func() {
|
resetDNSOnce.Do(func() {
|
||||||
// See corresponding comment in setDNS.
|
// See corresponding comment in setDNS.
|
||||||
if windowsHasLocalDnsServerRunning() {
|
if windowsHasLocalDnsServerRunning() {
|
||||||
file := absHomeDir(forwardersFilename)
|
file := absHomeDir(windowsForwardersFilename)
|
||||||
content, err := os.ReadFile(file)
|
content, err := os.ReadFile(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Error().Err(err).Msg("could not read forwarders settings")
|
mainLog.Load().Error().Err(err).Msg("could not read forwarders settings")
|
||||||
|
|||||||
+3
-1
@@ -797,7 +797,9 @@ func withEachPhysicalInterfaces(excludeIfaceName, context string, f func(i *net.
|
|||||||
}
|
}
|
||||||
// TODO: investigate whether we should report this error?
|
// TODO: investigate whether we should report this error?
|
||||||
if err := f(netIface); err == nil {
|
if err := f(netIface); err == nil {
|
||||||
mainLog.Load().Debug().Msgf("%s for interface %q successfully", context, i.Name)
|
if context != "" {
|
||||||
|
mainLog.Load().Debug().Msgf("%s for interface %q successfully", context, i.Name)
|
||||||
|
}
|
||||||
} else if !errors.Is(err, errSaveCurrentStaticDNSNotSupported) {
|
} else if !errors.Is(err, errSaveCurrentStaticDNSNotSupported) {
|
||||||
mainLog.Load().Err(err).Msgf("%s for interface %q failed", context, i.Name)
|
mainLog.Load().Err(err).Msgf("%s for interface %q failed", context, i.Name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package cli
|
||||||
|
|
||||||
|
var supportedSelfDelete = true
|
||||||
|
|
||||||
|
func selfDeleteExe() error { return nil }
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
// Copied from https://github.com/secur30nly/go-self-delete
|
||||||
|
// with modification to suitable for ctrld usage.
|
||||||
|
|
||||||
|
/*
|
||||||
|
License: MIT Licence
|
||||||
|
|
||||||
|
References:
|
||||||
|
- https://github.com/LloydLabs/delete-self-poc
|
||||||
|
- https://twitter.com/jonasLyk/status/1350401461985955840
|
||||||
|
*/
|
||||||
|
|
||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
var supportedSelfDelete = false
|
||||||
|
|
||||||
|
type FILE_RENAME_INFO struct {
|
||||||
|
Union struct {
|
||||||
|
ReplaceIfExists bool
|
||||||
|
Flags uint32
|
||||||
|
}
|
||||||
|
RootDirectory windows.Handle
|
||||||
|
FileNameLength uint32
|
||||||
|
FileName [1]uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type FILE_DISPOSITION_INFO struct {
|
||||||
|
DeleteFile bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func dsOpenHandle(pwPath *uint16) (windows.Handle, error) {
|
||||||
|
handle, err := windows.CreateFile(
|
||||||
|
pwPath,
|
||||||
|
windows.DELETE,
|
||||||
|
0,
|
||||||
|
nil,
|
||||||
|
windows.OPEN_EXISTING,
|
||||||
|
windows.FILE_ATTRIBUTE_NORMAL,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return handle, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func dsRenameHandle(hHandle windows.Handle) error {
|
||||||
|
var fRename FILE_RENAME_INFO
|
||||||
|
DS_STREAM_RENAME, err := windows.UTF16FromString(":deadbeef")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
lpwStream := &DS_STREAM_RENAME[0]
|
||||||
|
fRename.FileNameLength = uint32(unsafe.Sizeof(lpwStream))
|
||||||
|
|
||||||
|
windows.NewLazyDLL("kernel32.dll").NewProc("RtlCopyMemory").Call(
|
||||||
|
uintptr(unsafe.Pointer(&fRename.FileName[0])),
|
||||||
|
uintptr(unsafe.Pointer(lpwStream)),
|
||||||
|
unsafe.Sizeof(lpwStream),
|
||||||
|
)
|
||||||
|
|
||||||
|
err = windows.SetFileInformationByHandle(
|
||||||
|
hHandle,
|
||||||
|
windows.FileRenameInfo,
|
||||||
|
(*byte)(unsafe.Pointer(&fRename)),
|
||||||
|
uint32(unsafe.Sizeof(fRename)+unsafe.Sizeof(lpwStream)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func dsDepositeHandle(hHandle windows.Handle) error {
|
||||||
|
var fDelete FILE_DISPOSITION_INFO
|
||||||
|
fDelete.DeleteFile = true
|
||||||
|
|
||||||
|
err := windows.SetFileInformationByHandle(
|
||||||
|
hHandle,
|
||||||
|
windows.FileDispositionInfo,
|
||||||
|
(*byte)(unsafe.Pointer(&fDelete)),
|
||||||
|
uint32(unsafe.Sizeof(fDelete)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func selfDeleteExe() error {
|
||||||
|
var wcPath [windows.MAX_PATH + 1]uint16
|
||||||
|
var hCurrent windows.Handle
|
||||||
|
|
||||||
|
_, err := windows.GetModuleFileName(0, &wcPath[0], windows.MAX_PATH)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
hCurrent, err = dsOpenHandle(&wcPath[0])
|
||||||
|
if err != nil || hCurrent == windows.InvalidHandle {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dsRenameHandle(hCurrent); err != nil {
|
||||||
|
_ = windows.CloseHandle(hCurrent)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_ = windows.CloseHandle(hCurrent)
|
||||||
|
|
||||||
|
hCurrent, err = dsOpenHandle(&wcPath[0])
|
||||||
|
if err != nil || hCurrent == windows.InvalidHandle {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := dsDepositeHandle(hCurrent); err != nil {
|
||||||
|
_ = windows.CloseHandle(hCurrent)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return windows.CloseHandle(hCurrent)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user