diff --git a/security/dns.go b/security/dns.go index 5dc256aa..b6afdefe 100644 --- a/security/dns.go +++ b/security/dns.go @@ -1,5 +1,3 @@ -// +build !windows - package security import ( @@ -18,6 +16,8 @@ func DnsServers() []string { return dnsLinux() case "darwin": return dnsMacOS() + case "windows": + return dnsWindows() default: return []string{runtime.GOOS} } @@ -56,3 +56,10 @@ func dnsMacOS() []string { return []string{} } + +func dnsWindows() []string { + + cmd := exec.Command("powershell.exe", "-NoProfile", "Get-DnsClientServerAddress | Select-Object –ExpandProperty ServerAddresses") + + return []string{wtf.ExecuteCommand(cmd)} +} diff --git a/security/dns_windows.go b/security/dns_windows.go deleted file mode 100644 index 544def20..00000000 --- a/security/dns_windows.go +++ /dev/null @@ -1,14 +0,0 @@ -// +build windows - -package security - -import ( - "os/exec" - - "github.com/wtfutil/wtf/wtf" -) - -func DnsServers() []string { - cmd := exec.Command("powershell.exe", "Get-DnsClientServerAddress | Select-Object –ExpandProperty ServerAddresses") - return []string{wtf.ExecuteCommand(cmd)} -} diff --git a/security/firewall.go b/security/firewall.go index 6c5864ee..5e246e27 100644 --- a/security/firewall.go +++ b/security/firewall.go @@ -20,6 +20,8 @@ func FirewallState() string { return firewallStateLinux() case "darwin": return firewallStateMacOS() + case "windows": + return firewallStateWindows() default: return "" } @@ -31,6 +33,8 @@ func FirewallStealthState() string { return firewallStealthStateLinux() case "darwin": return firewallStealthStateMacOS() + case "windows": + return firewallStealthStateWindows() default: return "" } @@ -56,7 +60,7 @@ func firewallStateLinux() string { // might be very Ubuntu specific return "[green]Enabled[white]" } } else { - return "[red]NA[white]" + return "[red]N/A[white]" } } @@ -67,8 +71,38 @@ func firewallStateMacOS() string { return statusLabel(str) } +func firewallStateWindows() string { + // The raw way to do this in PS, not using netsh, nor registry, is the following: + // if (((Get-NetFirewallProfile | select name,enabled) + // | where { $_.Enabled -eq $True } | measure ).Count -eq 3) + // { Write-Host "OK" -ForegroundColor Green} else { Write-Host "OFF" -ForegroundColor Red } + + cmd := exec.Command("powershell.exe", "-NoProfile", + "-Command", "& { ((Get-NetFirewallProfile | select name,enabled) | where { $_.Enabled -eq $True } | measure ).Count }") + + fwStat := wtf.ExecuteCommand(cmd) + fwStat = strings.TrimSpace(fwStat) // Always sanitize PowerShell output: "3\r\n" + //fmt.Printf("%d %q\n", len(fwStat), fwStat) + + switch fwStat { + case "3": + return "[green]Good[white] (3/3)" + case "2": + return "[orange]Poor[white] (2/3)" + case "1": + return "[yellow]Bad[white] (1/3)" + case "0": + return "[red]Disabled[white]" + default: + return "[white]N/A[white]" + } +} + +/* -------------------- Getting Stealth State ------------------- */ +// "Stealth": Not responding to pings from unauthorized devices + func firewallStealthStateLinux() string { - return "[red]NA[white]" + return "[white]N/A[white]" } func firewallStealthStateMacOS() string { @@ -78,6 +112,11 @@ func firewallStealthStateMacOS() string { return statusLabel(str) } +func firewallStealthStateWindows() string { + return "[white]N/A[white]" +} + + func statusLabel(str string) string { label := "off" diff --git a/security/users.go b/security/users.go index af40eb44..88b08658 100644 --- a/security/users.go +++ b/security/users.go @@ -1,5 +1,3 @@ -// +build !windows - package security // http://applehelpwriter.com/2017/05/21/how-to-reveal-hidden-users/ @@ -20,6 +18,8 @@ func LoggedInUsers() []string { return loggedInUsersLinux() case "darwin": return loggedInUsersMacOs() + case "windows": + return loggedInUsersWindows() default: return []string{} } @@ -66,12 +66,10 @@ func loggedInUsersLinux() []string { clean = false } } - if clean { cleaned = append(cleaned, col[0]) } } - } return cleaned @@ -83,3 +81,20 @@ func loggedInUsersMacOs() []string { return cleanUsers(strings.Split(users, "\n")) } + +func loggedInUsersWindows() []string { + // We can use either one: + // (Get-WMIObject -class Win32_ComputerSystem | select username).username + // [System.Security.Principal.WindowsIdentity]::GetCurrent().Name + // The original was: + // cmd := exec.Command("powershell.exe", "(query user) -replace '\\s{2,}', ','") + // But that didn't work! + // The real powershell command reads: + // powershell.exe -NoProfile -Command "& { [System.Security.Principal.WindowsIdentity]::GetCurrent().Name }" + // But we here have to write it as: + cmd := exec.Command("powershell.exe", "-NoProfile", "-Command", "& { [System.Security.Principal.WindowsIdentity]::GetCurrent().Name }") + // ToDo: Make list for multi-user systems + + users := wtf.ExecuteCommand(cmd) + return cleanUsers(strings.Split(users, "\n")) +} diff --git a/security/users_windows.go b/security/users_windows.go deleted file mode 100644 index 5d5d937d..00000000 --- a/security/users_windows.go +++ /dev/null @@ -1,25 +0,0 @@ -// +build windows - -package security - -import ( - "os/exec" - "strings" - - "github.com/wtfutil/wtf/wtf" -) - -func LoggedInUsers() []string { - cmd := exec.Command("powershell.exe", "(query user) -replace '\\s{2,}', ','") - users := wtf.ExecuteCommand(cmd) - return cleanUsers(strings.Split(users, "\n")[1:]) -} - -func cleanUsers(users []string) []string { - cleaned := make([]string, 0) - for _, user := range users { - usr := strings.Split(user, ",") - cleaned = append(cleaned, usr[0]) - } - return cleaned -} diff --git a/security/widget.go b/security/widget.go index f4f67d0a..2bd39415 100644 --- a/security/widget.go +++ b/security/widget.go @@ -1,5 +1,3 @@ -// +build !windows - package security import ( @@ -25,6 +23,11 @@ func NewWidget(app *tview.Application) *Widget { /* -------------------- Exported Functions -------------------- */ func (widget *Widget) Refresh() { + + if widget.Disabled() { + return + } + data := NewSecurityData() data.Fetch() @@ -38,12 +41,22 @@ func (widget *Widget) contentFrom(data *SecurityData) string { str = str + fmt.Sprintf(" %8s: %s\n", "Network", data.WifiName) str = str + fmt.Sprintf(" %8s: %s\n", "Crypto", data.WifiEncryption) str = str + "\n" - str = str + " [red]Firewall[white] [red]DNS[white]\n" - str = str + fmt.Sprintf(" %8s: [%s]%-3s[white] %-16s\n", "Enabled", widget.labelColor(data.FirewallEnabled), data.FirewallEnabled, data.DnsAt(0)) - str = str + fmt.Sprintf(" %8s: [%s]%-3s[white] %-16s\n", "Stealth", widget.labelColor(data.FirewallStealth), data.FirewallStealth, data.DnsAt(1)) + + str = str + " [red]Firewall[white]\n" + str = str + fmt.Sprintf(" %8s: %4s\n", "Status", data.FirewallEnabled) + str = str + fmt.Sprintf(" %8s: %4s\n", "Stealth", data.FirewallStealth) str = str + "\n" + str = str + " [red]Users[white]\n" - str = str + fmt.Sprintf(" %s", strings.Join(data.LoggedInUsers, ", ")) + str = str + fmt.Sprintf(" %s", strings.Join(data.LoggedInUsers, "\n ")) + str = str + "\n" + + str = str + " [red]DNS[white]\n" + //str = str + fmt.Sprintf(" %8s: [%s]%-3s[white] %-16s\n", "Enabled", widget.labelColor(data.FirewallEnabled), data.FirewallEnabled, data.DnsAt(0)) + //str = str + fmt.Sprintf(" %8s: [%s]%-3s[white] %-16s\n", "Stealth", widget.labelColor(data.FirewallStealth), data.FirewallStealth, data.DnsAt(1)) + str = str + fmt.Sprintf(" %12s\n", data.DnsAt(0)) + str = str + fmt.Sprintf(" %12s\n", data.DnsAt(1)) + str = str + "\n" return str } diff --git a/security/widget_windows.go b/security/widget_windows.go deleted file mode 100644 index 5fa2e4c3..00000000 --- a/security/widget_windows.go +++ /dev/null @@ -1,53 +0,0 @@ -// +build windows - -package security - -import ( - "fmt" - "strings" - - "github.com/rivo/tview" - "github.com/wtfutil/wtf/wtf" -) - -type Widget struct { - wtf.TextWidget -} - -func NewWidget(app *tview.Application) *Widget { - widget := Widget{ - TextWidget: wtf.NewTextWidget(app, "Security", "security", false), - } - - return &widget -} - -/* -------------------- Exported Functions -------------------- */ - -func (widget *Widget) Refresh() { - if widget.Disabled() { - return - } - - data := NewSecurityData() - data.Fetch() - - widget.View.SetText(widget.contentFrom(data)) -} - -/* -------------------- Unexported Functions -------------------- */ - -func (widget *Widget) contentFrom(data *SecurityData) string { - str := " [red]WiFi[white]\n" - str = str + fmt.Sprintf(" %8s: %s\n", "Network", data.WifiName) - str = str + fmt.Sprintf(" %8s: %s\n", "Crypto", data.WifiEncryption) - str = str + "\n" - str = str + " [red]Firewall[white] [red]DNS[white]\n" - str = str + fmt.Sprintf(" %8s: %4s %12s\n", "Enabled", data.FirewallEnabled, data.DnsAt(0)) - str = str + fmt.Sprintf(" %8s: %4s %12s\n", "Stealth", data.FirewallStealth, data.DnsAt(1)) - str = str + "\n" - str = str + " [red]Users[white]\n" - str = str + fmt.Sprintf(" %s", strings.Join(data.LoggedInUsers, ",")) - - return str -}