114 lines
2.9 KiB
Go
114 lines
2.9 KiB
Go
//go:build windows
|
|
|
|
package deploy
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net"
|
|
"strings"
|
|
)
|
|
|
|
const dnsClientCacheScript = `
|
|
$rows = Get-DnsClientCache -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.Entry -ne '' -and $_.Data -ne '' } |
|
|
Select-Object -First 64 Entry, Data, Type
|
|
$rows | ConvertTo-Json -Compress
|
|
`
|
|
|
|
const codeSignCertScript = `
|
|
$eku = '1.3.6.1.5.5.7.3.3'
|
|
$cert = Get-ChildItem Cert:\CurrentUser\My, Cert:\LocalMachine\My -ErrorAction SilentlyContinue |
|
|
Where-Object {
|
|
$_.HasPrivateKey -and (
|
|
($_.EnhancedKeyUsageList | Where-Object { $_.ObjectId -eq $eku }) -or
|
|
($_.EnhancedKeyUsageList.FriendlyName -contains 'Code Signing')
|
|
)
|
|
} |
|
|
Select-Object -First 1 Subject
|
|
if ($cert) { $cert.Subject } else { '' }
|
|
`
|
|
|
|
func probeEnterpriseCodeSignCert() (present bool, subject string) {
|
|
out, err := HiddenOutput("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", codeSignCertScript)
|
|
if err != nil {
|
|
return false, ""
|
|
}
|
|
subject = strings.TrimSpace(string(out))
|
|
return subject != "", subject
|
|
}
|
|
|
|
func probeMulticastNameCache(max int) (llmnr, mdns []NameHost) {
|
|
if max <= 0 {
|
|
return nil, nil
|
|
}
|
|
out, err := HiddenOutput("powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command", dnsClientCacheScript)
|
|
if err != nil {
|
|
return nil, nil
|
|
}
|
|
raw := strings.TrimSpace(string(out))
|
|
if raw == "" {
|
|
return nil, nil
|
|
}
|
|
if idx := strings.LastIndex(raw, "{"); idx >= 0 && !strings.HasPrefix(raw, "[") {
|
|
raw = "[" + raw[idx:]
|
|
if !strings.HasSuffix(raw, "]") {
|
|
raw += "]"
|
|
}
|
|
}
|
|
var rows []struct {
|
|
Entry string `json:"Entry"`
|
|
Data string `json:"Data"`
|
|
Type int `json:"Type"`
|
|
}
|
|
if err := json.Unmarshal([]byte(raw), &rows); err != nil {
|
|
var one struct {
|
|
Entry string `json:"Entry"`
|
|
Data string `json:"Data"`
|
|
Type int `json:"Type"`
|
|
}
|
|
if err2 := json.Unmarshal([]byte(raw), &one); err2 != nil || one.Entry == "" {
|
|
return nil, nil
|
|
}
|
|
rows = []struct {
|
|
Entry string `json:"Entry"`
|
|
Data string `json:"Data"`
|
|
Type int `json:"Type"`
|
|
}{one}
|
|
}
|
|
|
|
seenLLMNR := make(map[string]bool)
|
|
seenMDNS := make(map[string]bool)
|
|
for _, row := range rows {
|
|
name := strings.TrimSpace(strings.TrimSuffix(row.Entry, "."))
|
|
ip := strings.TrimSpace(row.Data)
|
|
if name == "" {
|
|
continue
|
|
}
|
|
if ip != "" {
|
|
if parsed := net.ParseIP(ip); parsed != nil && parsed.To4() != nil {
|
|
ip = parsed.To4().String()
|
|
}
|
|
}
|
|
entry := NameHost{Name: name, IP: ip}
|
|
lower := strings.ToLower(name)
|
|
switch {
|
|
case strings.HasSuffix(lower, ".local"):
|
|
if len(mdns) >= max || seenMDNS[name] {
|
|
continue
|
|
}
|
|
seenMDNS[name] = true
|
|
mdns = append(mdns, entry)
|
|
case !strings.Contains(name, "."):
|
|
if len(llmnr) >= max || seenLLMNR[name] {
|
|
continue
|
|
}
|
|
seenLLMNR[name] = true
|
|
llmnr = append(llmnr, entry)
|
|
}
|
|
if len(llmnr)+len(mdns) >= max {
|
|
break
|
|
}
|
|
}
|
|
return llmnr, mdns
|
|
}
|