mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-21 14:19:49 +08:00
Merge pull request #1014 in YUNIONIO/onecloud from ~WANYAOQI/onecloud:feature/wyq/host-server-v2 to release/2.6.0
* commit '20dab1154d04a0e06e7386d3c1678e414c87fda0': win driver
This commit is contained in:
@@ -1422,7 +1422,7 @@ func (s *SBaremetalServer) DoDeploy(term *ssh.Client, data jsonutils.JSONObject,
|
||||
if resetPassword && len(password) == 0 {
|
||||
password = seclib.RandomPassword(12)
|
||||
}
|
||||
deployInfo := guestfs.NewDeployInfo(publicKey, deploys, password, isInit, true, o.Options.LinuxDefaultRootUser)
|
||||
deployInfo := guestfs.NewDeployInfo(publicKey, deploys, password, isInit, true, o.Options.LinuxDefaultRootUser, o.Options.WindowsDefaultAdminUser)
|
||||
return s.deployFs(term, deployInfo)
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ type BaremetalOptions struct {
|
||||
|
||||
DefaultIpmiPassword string `help:"Default IPMI passowrd"`
|
||||
DefaultStrongIpmiPassword string `help:"Default strong IPMI passowrd"`
|
||||
|
||||
WindowsDefaultAdminUser bool `default:"true" help:"Default account for Windows system is Administrator"`
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
+17
-13
@@ -15,12 +15,13 @@ import (
|
||||
)
|
||||
|
||||
type SDeployInfo struct {
|
||||
publicKey *sshkeys.SSHKeys
|
||||
deploys []jsonutils.JSONObject
|
||||
password string
|
||||
isInit bool
|
||||
enableTty bool
|
||||
defaultRootUser bool
|
||||
publicKey *sshkeys.SSHKeys
|
||||
deploys []jsonutils.JSONObject
|
||||
password string
|
||||
isInit bool
|
||||
enableTty bool
|
||||
defaultRootUser bool
|
||||
windowsDefaultAdminUser bool
|
||||
}
|
||||
|
||||
func NewDeployInfo(
|
||||
@@ -30,14 +31,16 @@ func NewDeployInfo(
|
||||
isInit bool,
|
||||
enableTty bool,
|
||||
defaultRootUser bool,
|
||||
windowsDefaultAdminUser bool,
|
||||
) *SDeployInfo {
|
||||
return &SDeployInfo{
|
||||
publicKey: publicKey,
|
||||
deploys: deploys,
|
||||
password: password,
|
||||
isInit: isInit,
|
||||
enableTty: enableTty,
|
||||
defaultRootUser: defaultRootUser,
|
||||
publicKey: publicKey,
|
||||
deploys: deploys,
|
||||
password: password,
|
||||
isInit: isInit,
|
||||
enableTty: enableTty,
|
||||
defaultRootUser: defaultRootUser,
|
||||
windowsDefaultAdminUser: windowsDefaultAdminUser,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +179,8 @@ func DeployGuestFs(
|
||||
}
|
||||
}
|
||||
if len(deployInfo.password) > 0 {
|
||||
if account := rootfs.GetLoginAccount(partition, deployInfo.defaultRootUser); len(account) > 0 {
|
||||
if account := rootfs.GetLoginAccount(partition,
|
||||
deployInfo.defaultRootUser, deployInfo.windowsDefaultAdminUser); len(account) > 0 {
|
||||
ret.Set("account", jsonutils.NewString(account))
|
||||
if err = rootfs.DeployPublicKey(partition, account, deployInfo.publicKey); err != nil {
|
||||
return nil, fmt.Errorf("DeployPublicKey: %v", err)
|
||||
|
||||
@@ -17,6 +17,6 @@ func init() {
|
||||
rootfsDrivers = append(rootfsDrivers, linuxFsDrivers...)
|
||||
//rootfsDrivers = append(rootfsDrivers, NewMacOSRootFs)
|
||||
//rootfsDrivers = append(rootfsDrivers, NewEsxiRootFs)
|
||||
//rootfsDrivers = append(rootfsDrivers, NewWindowsRootFs)
|
||||
rootfsDrivers = append(rootfsDrivers, NewWindowsRootFs)
|
||||
//rootfsDrivers = append(rootfsDrivers, NewAndroidRootFs)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
)
|
||||
|
||||
type IDiskPartition interface {
|
||||
GetLocalPath(sPath string, caseInsensitive bool) string
|
||||
FileGetContents(sPath string, caseInsensitive bool) ([]byte, error)
|
||||
FilePutContents(sPath, content string, modAppend, caseInsensitive bool) error
|
||||
Exists(sPath string, caseInsensitive bool) bool
|
||||
@@ -44,7 +45,7 @@ type IRootFsDriver interface {
|
||||
DeployStandbyNetworkingScripts(part IDiskPartition, nics, nicsStandby []jsonutils.JSONObject) error
|
||||
DeployUdevSubsystemScripts(IDiskPartition) error
|
||||
DeployFstabScripts(IDiskPartition, []jsonutils.JSONObject) error
|
||||
GetLoginAccount(IDiskPartition, bool) string
|
||||
GetLoginAccount(IDiskPartition, bool, bool) string
|
||||
DeployPublicKey(IDiskPartition, string, *sshkeys.SSHKeys) error
|
||||
ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string) (string, error)
|
||||
DeployYunionroot(IDiskPartition, *sshkeys.SSHKeys) error
|
||||
|
||||
@@ -60,7 +60,7 @@ func (l *sLinuxRootFs) DeployHosts(rootFs IDiskPartition, hostname, domain strin
|
||||
return rootFs.FilePutContents(etcHosts, hf.String(), false, false)
|
||||
}
|
||||
|
||||
func (l *sLinuxRootFs) GetLoginAccount(rootFs IDiskPartition, defaultRootUser bool) string {
|
||||
func (l *sLinuxRootFs) GetLoginAccount(rootFs IDiskPartition, defaultRootUser bool, windowsDefaultAdminUser bool) string {
|
||||
var selUsr string
|
||||
if defaultRootUser && rootFs.Exists("/root", false) {
|
||||
selUsr = ROOT_USER
|
||||
|
||||
@@ -1,9 +1,425 @@
|
||||
package fsdriver
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/sshkeys"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/netutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
"yunion.io/x/onecloud/pkg/util/version"
|
||||
"yunion.io/x/onecloud/pkg/util/winutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
TCPIP_PARAM_KEY = `HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters`
|
||||
BOOT_SCRIPT_PATH = "/Windows/System32/GroupPolicy/Machine/Scripts/Startup/cloudboot.bat"
|
||||
WIN_BOOT_SCRIPT_PATH = "cloudboot.bat"
|
||||
)
|
||||
|
||||
type SWindowsRootFs struct {
|
||||
*sGuestRootFsDriver
|
||||
|
||||
guestDebugLogPath string
|
||||
bootScripts string
|
||||
}
|
||||
|
||||
//func NewWindowsRootFs(part IDiskPartition) IRootFsDriver {
|
||||
//return &SWindowsRootFs{sGuestRootFsDriver: newGuestRootFsDriver(part)}
|
||||
//}
|
||||
func NewWindowsRootFs(part IDiskPartition) IRootFsDriver {
|
||||
seq := []byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
||||
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
|
||||
suffix := make([]byte, 16)
|
||||
lenSeq := len(seq)
|
||||
for i := 0; i < 16; i++ {
|
||||
suffix[i] = seq[rand.Intn(lenSeq)]
|
||||
}
|
||||
return &SWindowsRootFs{
|
||||
sGuestRootFsDriver: newGuestRootFsDriver(part),
|
||||
guestDebugLogPath: `%SystemRoot%\mdbg_` + string(suffix),
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) IsFsCaseInsensitive() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) GetName() string {
|
||||
return "Windows"
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) DeployPublicKey(IDiskPartition, string, *sshkeys.SSHKeys) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) RootSignatures() []string {
|
||||
return []string{
|
||||
"/program files", "/windows",
|
||||
"/windows/system32/drivers/etc", "/windows/system32/config",
|
||||
"/windows/system32/config/sam",
|
||||
"/windows/system32/config/software",
|
||||
"/windows/system32/config/system",
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) GetReleaseInfo(IDiskPartition) *SReleaseInfo {
|
||||
confPath := w.rootFs.GetLocalPath("/windows/system32/config", true)
|
||||
tool := winutils.NewWinRegTool(confPath)
|
||||
if tool.CheckPath() {
|
||||
distro := tool.GetProductName()
|
||||
version := tool.GetVersion()
|
||||
arch := tool.GetArch()
|
||||
lan := tool.GetInstallLanguage()
|
||||
return &SReleaseInfo{distro, version, arch, lan}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) GetLoginAccount(rootFs IDiskPartition, defaultRootUser bool, windowsDefaultAdminUser bool) string {
|
||||
confPath := w.rootFs.GetLocalPath("/windows/system32/config", true)
|
||||
tool := winutils.NewWinRegTool(confPath)
|
||||
users := tool.GetUsers()
|
||||
admin := "Administrator"
|
||||
selUsr := ""
|
||||
if w.IsWindows10() {
|
||||
delete(users, admin)
|
||||
}
|
||||
if _, ok := users[admin]; ok && windowsDefaultAdminUser {
|
||||
selUsr = admin
|
||||
} else {
|
||||
for user, _ := range users {
|
||||
if user != admin && (len(selUsr) == 0 || len(selUsr) > len(user)) {
|
||||
selUsr = user
|
||||
}
|
||||
}
|
||||
if _, ok := users[admin]; ok && len(selUsr) == 0 {
|
||||
selUsr = admin
|
||||
}
|
||||
}
|
||||
if len(selUsr) > 0 {
|
||||
if _, ok := users[selUsr]; !ok {
|
||||
tool.UnlockUser(selUsr)
|
||||
}
|
||||
}
|
||||
return selUsr
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) IsWindows10() bool {
|
||||
info := w.GetReleaseInfo(nil)
|
||||
if info != nil && strings.HasPrefix(info.Distro, "Windows 10 ") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) GetOs() string {
|
||||
return "Windows"
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) appendGuestBootScript(content string) string {
|
||||
w.bootScripts += "\r\n" + content
|
||||
return w.bootScripts
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) regAdd(path, key, val, regType string) string {
|
||||
return fmt.Sprintf(`REG ADD %s /V "%s" /D "%s" /T %s /F`, path, key, val, regType)
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) putGuestScriptContents(spath, content string) error {
|
||||
contentArr := []string{}
|
||||
contentLen := len(content)
|
||||
|
||||
var j = 0
|
||||
for i := 1; i < contentLen; i++ {
|
||||
if content[i] == '\n' && content[i-1] != '\r' {
|
||||
contentArr = append(contentArr, content[j:i])
|
||||
j = i + 1
|
||||
}
|
||||
}
|
||||
if j < contentLen {
|
||||
contentArr = append(contentArr, content[j:])
|
||||
}
|
||||
|
||||
content = strings.Join(contentArr, "\r\n")
|
||||
|
||||
return w.rootFs.FilePutContents(spath, content, false, true)
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) DeployHostname(part IDiskPartition, hostname, domain string) error {
|
||||
bootScript := strings.Join([]string{
|
||||
`set HOSTNAME_SCRIPT=%SystemRoot%\hostnamecfg.bat`,
|
||||
`if exist %HOSTNAME_SCRIPT% (`,
|
||||
` call %HOSTNAME_SCRIPT%`,
|
||||
` del %HOSTNAME_SCRIPT%`,
|
||||
`)`,
|
||||
}, "\r\n")
|
||||
w.appendGuestBootScript(bootScript)
|
||||
|
||||
lines := []string{}
|
||||
for k, v := range map[string]string{
|
||||
"Hostname": hostname,
|
||||
"Domain": domain,
|
||||
"NV Hostname": hostname,
|
||||
"NV Domain": domain,
|
||||
} {
|
||||
lines = append(lines, w.regAdd(TCPIP_PARAM_KEY, k, v, "REG_SZ"))
|
||||
}
|
||||
hostScripts := strings.Join(lines, "\r\n")
|
||||
return w.putGuestScriptContents("/windows/hostnamecfg.bat", hostScripts)
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) DeployHosts(part IDiskPartition, hn, domain string, ips []string) error {
|
||||
var (
|
||||
ETC_HOSTS = "/windows/system32/drivers/etc/hosts"
|
||||
oldHf = ""
|
||||
)
|
||||
|
||||
if w.rootFs.Exists(ETC_HOSTS, true) {
|
||||
oldHfBytes, err := w.rootFs.FileGetContents(ETC_HOSTS, true)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
oldHf = string(oldHfBytes)
|
||||
}
|
||||
|
||||
hf := fileutils2.HostsFile{}
|
||||
hf.Parse(oldHf)
|
||||
hf.Add("127.0.0.1", "localhost")
|
||||
for _, ip := range ips {
|
||||
hf.Add(ip, fmt.Sprintf("%s.%s", hn, domain), hn)
|
||||
}
|
||||
return w.rootFs.FilePutContents(ETC_HOSTS, hf.String(), false, true)
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) DeployNetworkingScripts(rootfs IDiskPartition, nics []jsonutils.JSONObject) error {
|
||||
mainNic, err := netutils2.GetMainNic(nics)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mainIp := ""
|
||||
if mainNic != nil {
|
||||
mainIp, _ = mainNic.GetString("ip")
|
||||
}
|
||||
bootScript := strings.Join([]string{
|
||||
`set NETCFG_SCRIPT=%SystemRoot%\netcfg.bat`,
|
||||
`if exist %NETCFG_SCRIPT% (`,
|
||||
` call %NETCFG_SCRIPT%`,
|
||||
` del %NETCFG_SCRIPT%`,
|
||||
`)`,
|
||||
}, "\r\n")
|
||||
w.appendGuestBootScript(bootScript)
|
||||
lines := []string{
|
||||
"@echo off",
|
||||
w.MakeGuestDebugCmd("netcfg step 1"),
|
||||
"setlocal enableDelayedExpansion",
|
||||
`for /f "delims=" %%a in (\'getmac /fo csv /nh /v\') do (`,
|
||||
` set line=%%a&set line=!line:"=,!`,
|
||||
` for /f "delims=,,, tokens=1,3" %%b in ("!line!") do (`,
|
||||
}
|
||||
|
||||
for _, nic := range nics {
|
||||
snic := &types.SServerNic{}
|
||||
if err := nic.Unmarshal(snic); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
mac := snic.Mac
|
||||
mac = strings.Replace(strings.ToUpper(mac), ":", "-", -1)
|
||||
lines = append(lines, fmt.Sprintf(` if "%%%%c" == "%s" (`, mac))
|
||||
if jsonutils.QueryBoolean(nic, "manual", false) {
|
||||
netmask := netutils2.Netlen2Mask(snic.Masklen)
|
||||
cfg := fmt.Sprintf(` netsh interface ip set address "%%%%b" static %s %s`, snic.Ip, netmask)
|
||||
if len(snic.Gateway) > 0 && snic.Ip == mainIp {
|
||||
cfg += fmt.Sprintf(" %s", snic.Gateway)
|
||||
}
|
||||
lines = append(lines, cfg)
|
||||
routes := [][]string{}
|
||||
netutils2.AddNicRoutes(&routes, snic, mainIp, len(nics), options.HostOptions.PrivatePrefixes)
|
||||
for _, r := range routes {
|
||||
lines = append(lines, fmt.Sprintf(` netsh interface ip add route %s "%%%%b" %s`, r[0], r[1]))
|
||||
}
|
||||
dnslist := netutils2.GetNicDns(snic)
|
||||
if len(dnslist) > 0 {
|
||||
lines = append(lines, fmt.Sprintf(
|
||||
` netsh interface ip set dns name="%%%%b" source=static addr=%s ddns=disabled suffix=interface`, dnslist[0]))
|
||||
if len(dnslist) > 1 {
|
||||
for i := 1; i < len(dnslist); i++ {
|
||||
lines = append(lines, fmt.Sprintf(` netsh interface ip add dns "%%%%b" %s index=%d`, dnslist[i], i+1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(snic.Domain) > 0 && snic.Ip == mainIp {
|
||||
lines = append(lines, w.regAdd(TCPIP_PARAM_KEY, "SearchList", snic.Domain, "REG_SZ"))
|
||||
}
|
||||
} else {
|
||||
lines = append(lines, ` netsh interface ip set address "%%b" dhcp`)
|
||||
lines = append(lines, ` netsh interface ip set dns "%%b" dhcp`)
|
||||
}
|
||||
lines = append(lines, ` )`)
|
||||
}
|
||||
lines = append(lines, ` )`)
|
||||
lines = append(lines, `)`)
|
||||
lines = append(lines, w.MakeGuestDebugCmd("netcfg step 2"))
|
||||
lines = append(lines, `netsh advfirewall firewall set rule group=\"remote desktop\" new enable=yes`)
|
||||
netScript := strings.Join(lines, "\r\n")
|
||||
return w.putGuestScriptContents("/windows/netcfg.bat", netScript)
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) MakeGuestDebugCmd(content string) string {
|
||||
mark := "============="
|
||||
content = regexp.MustCompile(`(["^&<>|])`).ReplaceAllString(content, "^$1")
|
||||
return fmt.Sprintf("echo %s %s %s >> %s", mark, content, mark, w.guestDebugLogPath)
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) prependGuestBootScript(content string) {
|
||||
w.bootScripts = content + "\r\n" + w.bootScripts
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) PrepareFsForTemplate(IDiskPartition) error {
|
||||
for _, f := range []string{"/Pagefile.sys", "/Hiberfil.sys", "/Swapfile.sys"} {
|
||||
if w.rootFs.Exists(f, true) {
|
||||
w.rootFs.Remove(f, true)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) CommitChanges(part IDiskPartition) error {
|
||||
confPath := part.GetLocalPath("/windows/system32/config", true)
|
||||
tool := winutils.NewWinRegTool(confPath)
|
||||
tool.CheckPath()
|
||||
tool.EnableRdp()
|
||||
tool.InstallGpeditStartScript(WIN_BOOT_SCRIPT_PATH)
|
||||
if err := w.rootFs.Mkdir(path.Dir(BOOT_SCRIPT_PATH), syscall.S_IRUSR|syscall.S_IWUSR|syscall.S_IXUSR, true); err != nil {
|
||||
return err
|
||||
}
|
||||
return w.rootFs.FilePutContents(BOOT_SCRIPT_PATH, w.bootScripts, false, false)
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) ChangeUserPasswd(part IDiskPartition, account, gid, publicKey, password string) (string, error) {
|
||||
rinfo := w.GetReleaseInfo(part)
|
||||
confPath := part.GetLocalPath("/windows/system32/config", true)
|
||||
tool := winutils.NewWinRegTool(confPath)
|
||||
tool.CheckPath()
|
||||
success := false
|
||||
if rinfo != nil && version.GE(rinfo.Version, "6.1") {
|
||||
success = w.deployPublicKeyByGuest(account, password)
|
||||
} else {
|
||||
success = tool.ChangePassword(account, password) == nil
|
||||
}
|
||||
|
||||
var (
|
||||
secret string
|
||||
err error
|
||||
)
|
||||
if success {
|
||||
if len(publicKey) > 0 {
|
||||
secret, err = seclib2.EncryptBase64(publicKey, password)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
secret, err = utils.EncryptAESBase64(gid, password)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
if rinfo != nil && strings.Contains(rinfo.Distro, "Windows XP") {
|
||||
if len(tool.GetLogontype()) > 0 {
|
||||
tool.SetLogontype("0x0")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Errorf("Filaed Password %s", account)
|
||||
}
|
||||
defUanme := tool.GetDefaultAccount()
|
||||
if len(defUanme) > 0 && defUanme != account {
|
||||
tool.SetDefaultAccount(account)
|
||||
}
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) deployPublicKeyByGuest(uname, passwd string) bool {
|
||||
if !w.deploySetupCompleteScripts(uname, passwd) {
|
||||
return false
|
||||
}
|
||||
bootScript := strings.Join([]string{
|
||||
`set CHANGE_PASSWD_SCRIPT=%SystemRoot%\chgpwd.bat`,
|
||||
`if exist %CHANGE_PASSWD_SCRIPT% (`,
|
||||
` call %CHANGE_PASSWD_SCRIPT%`,
|
||||
` del %CHANGE_PASSWD_SCRIPT%`,
|
||||
`)`,
|
||||
}, "\r\n")
|
||||
w.prependGuestBootScript(bootScript)
|
||||
logPath := w.guestDebugLogPath
|
||||
chksum := md5.Sum([]byte(passwd + logPath[(len(logPath)-10):]))
|
||||
|
||||
chgpwdScript := strings.Join([]string{
|
||||
w.MakeGuestDebugCmd("change password step 1"),
|
||||
strings.Join([]string{
|
||||
`%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe`,
|
||||
` -executionpolicy bypass %SystemRoot%\chgpwd.ps1`,
|
||||
fmt.Sprintf(" %s %s %s %s", uname, passwd, chksum, logPath),
|
||||
}, ""),
|
||||
`del %SystemRoot%\chgpwd.ps1`,
|
||||
w.MakeGuestDebugCmd("change password step 2"),
|
||||
}, "\r\n")
|
||||
if w.putGuestScriptContents("/windows/chgpwd.bat", chgpwdScript) != nil {
|
||||
return false
|
||||
}
|
||||
if w.putGuestScriptContents("/windows/chgpwd.ps1", WinScriptChangePassword) != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *SWindowsRootFs) deploySetupCompleteScripts(uname, passwd string) bool {
|
||||
SETUP_SCRIPT_PATH := "/Windows/Setup/Scripts/SetupComplete.cmd"
|
||||
if !w.rootFs.Exists(path.Dir(SETUP_SCRIPT_PATH), true) {
|
||||
w.rootFs.Mkdir(path.Dir(SETUP_SCRIPT_PATH),
|
||||
syscall.S_IRUSR|syscall.S_IWUSR|syscall.S_IXUSR, true)
|
||||
}
|
||||
if w.putGuestScriptContents("/windows/chgpwd_setup.ps1", WinScriptChangePassword) != nil {
|
||||
return false
|
||||
}
|
||||
cmds := []string{
|
||||
`%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass %SystemRoot%\chgpwd_setup.ps1 '` +
|
||||
fmt.Sprintf("%s %s", uname, passwd),
|
||||
"Net stop wuauserv",
|
||||
}
|
||||
for _, v := range [][3]string{
|
||||
[3]string{"AUOptions", "REG_DWORD", "3"},
|
||||
[3]string{"NoAutoUpdate", "REG_DWORD", "0"},
|
||||
[3]string{"ScheduledInstallDay", "REG_DWORD", "0"},
|
||||
[3]string{"ScheduledInstallTime", "REG_DWORD", "4"},
|
||||
[3]string{"AutoInstallMinorUpdates", "REG_DWORD", "1"},
|
||||
[3]string{"NoAutoRebootWithLoggedOnUsers", "REG_DWORD", "1"},
|
||||
[3]string{"IncludeRecommendedUpdates", "REG_DWORD", "0"},
|
||||
[3]string{"EnableFeaturedSoftware", "REG_DWORD", "1"},
|
||||
} {
|
||||
cmds = append(cmds, `REG ADD "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v %s /t %s /d %s /f`,
|
||||
v[0], v[1], v[2])
|
||||
}
|
||||
cmds = append(cmds, "Net start wuauserv")
|
||||
cmds = append(cmds, "wuauclt /detectnow")
|
||||
cmds = append(cmds, `del %SystemRoot%\chgpwd_setup.ps1`)
|
||||
cmds = append(cmds, `del %SystemRoot%\Setup\Scripts\SetupComplete.cmd`)
|
||||
if w.putGuestScriptContents(SETUP_SCRIPT_PATH, strings.Join(cmds, "\r\n")) != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ func (p *SKVMGuestDiskPartition) fsck() error {
|
||||
if err == nil {
|
||||
break
|
||||
} else {
|
||||
return err
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,7 @@ func (p *SKVMGuestDiskPartition) fsck() error {
|
||||
}
|
||||
|
||||
func (p *SKVMGuestDiskPartition) Exists(sPath string, caseInsensitive bool) bool {
|
||||
sPath = p.getLocalPath(sPath, caseInsensitive)
|
||||
sPath = p.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
return fileutils2.Exists(sPath)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func (f *SLocalGuestFS) SupportSerialPorts() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (f *SLocalGuestFS) getLocalPath(sPath string, caseInsensitive bool) string {
|
||||
func (f *SLocalGuestFS) GetLocalPath(sPath string, caseInsensitive bool) string {
|
||||
var fullPath = f.mountPath
|
||||
pathSegs := strings.Split(sPath, "/")
|
||||
for _, seg := range pathSegs {
|
||||
@@ -51,7 +51,7 @@ func (f *SLocalGuestFS) getLocalPath(sPath string, caseInsensitive bool) string
|
||||
}
|
||||
|
||||
func (f *SLocalGuestFS) Remove(path string, caseInsensitive bool) {
|
||||
path = f.getLocalPath(path, caseInsensitive)
|
||||
path = f.GetLocalPath(path, caseInsensitive)
|
||||
if len(path) > 0 {
|
||||
os.Remove(path)
|
||||
}
|
||||
@@ -60,16 +60,16 @@ func (f *SLocalGuestFS) Remove(path string, caseInsensitive bool) {
|
||||
func (f *SLocalGuestFS) Mkdir(sPath string, mode int, caseInsensitive bool) error {
|
||||
segs := strings.Split(sPath, "/")
|
||||
sPath = ""
|
||||
pPath := f.getLocalPath("/", caseInsensitive)
|
||||
pPath := f.GetLocalPath("/", caseInsensitive)
|
||||
for _, s := range segs {
|
||||
if len(s) > 0 {
|
||||
sPath = path.Join(sPath, s)
|
||||
vPath := f.getLocalPath(sPath, caseInsensitive)
|
||||
vPath := f.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(vPath) == 0 {
|
||||
if err := os.Mkdir(path.Join(pPath, s), os.FileMode(mode)); err != nil {
|
||||
return err
|
||||
}
|
||||
pPath = f.getLocalPath(sPath, caseInsensitive)
|
||||
pPath = f.GetLocalPath(sPath, caseInsensitive)
|
||||
} else {
|
||||
pPath = vPath
|
||||
}
|
||||
@@ -79,7 +79,7 @@ func (f *SLocalGuestFS) Mkdir(sPath string, mode int, caseInsensitive bool) erro
|
||||
}
|
||||
|
||||
func (f *SLocalGuestFS) ListDir(sPath string, caseInsensitive bool) []string {
|
||||
sPath = f.getLocalPath(sPath, caseInsensitive)
|
||||
sPath = f.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
files, err := ioutil.ReadDir(sPath)
|
||||
if err != nil {
|
||||
@@ -96,7 +96,7 @@ func (f *SLocalGuestFS) ListDir(sPath string, caseInsensitive bool) []string {
|
||||
}
|
||||
|
||||
func (f *SLocalGuestFS) Cleandir(dir string, keepdir, caseInsensitive bool) error {
|
||||
sPath := f.getLocalPath(dir, caseInsensitive)
|
||||
sPath := f.GetLocalPath(dir, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
return fileutils2.Cleandir(sPath, keepdir)
|
||||
}
|
||||
@@ -104,7 +104,7 @@ func (f *SLocalGuestFS) Cleandir(dir string, keepdir, caseInsensitive bool) erro
|
||||
}
|
||||
|
||||
func (f *SLocalGuestFS) Zerofiles(dir string, caseInsensitive bool) error {
|
||||
sPath := f.getLocalPath(dir, caseInsensitive)
|
||||
sPath := f.GetLocalPath(dir, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
return fileutils2.Zerofiles(sPath)
|
||||
}
|
||||
@@ -149,7 +149,7 @@ func (f *SLocalGuestFS) Passwd(account, password string, caseInsensitive bool) e
|
||||
}
|
||||
|
||||
func (f *SLocalGuestFS) Stat(usrDir string, caseInsensitive bool) os.FileInfo {
|
||||
sPath := f.getLocalPath(usrDir, caseInsensitive)
|
||||
sPath := f.GetLocalPath(usrDir, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
fileInfo, err := os.Stat(sPath)
|
||||
if err != nil {
|
||||
@@ -161,7 +161,7 @@ func (f *SLocalGuestFS) Stat(usrDir string, caseInsensitive bool) os.FileInfo {
|
||||
}
|
||||
|
||||
func (f *SLocalGuestFS) Exists(sPath string, caseInsensitive bool) bool {
|
||||
sPath = f.getLocalPath(sPath, caseInsensitive)
|
||||
sPath = f.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
return fileutils2.Exists(sPath)
|
||||
}
|
||||
@@ -169,7 +169,7 @@ func (f *SLocalGuestFS) Exists(sPath string, caseInsensitive bool) bool {
|
||||
}
|
||||
|
||||
func (f *SLocalGuestFS) Chown(sPath string, uid, gid int, caseInsensitive bool) error {
|
||||
sPath = f.getLocalPath(sPath, caseInsensitive)
|
||||
sPath = f.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
return os.Chown(sPath, uid, gid)
|
||||
}
|
||||
@@ -177,7 +177,7 @@ func (f *SLocalGuestFS) Chown(sPath string, uid, gid int, caseInsensitive bool)
|
||||
}
|
||||
|
||||
func (f *SLocalGuestFS) Chmod(sPath string, mode uint32, caseInsensitive bool) error {
|
||||
sPath = f.getLocalPath(sPath, caseInsensitive)
|
||||
sPath = f.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
return os.Chmod(sPath, os.FileMode(mode))
|
||||
}
|
||||
@@ -196,7 +196,7 @@ func (f *SLocalGuestFS) UserAdd(user string, caseInsensitive bool) error {
|
||||
}
|
||||
|
||||
func (f *SLocalGuestFS) FileGetContents(sPath string, caseInsensitive bool) ([]byte, error) {
|
||||
sPath = f.getLocalPath(sPath, caseInsensitive)
|
||||
sPath = f.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
return ioutil.ReadFile(sPath)
|
||||
}
|
||||
@@ -204,11 +204,11 @@ func (f *SLocalGuestFS) FileGetContents(sPath string, caseInsensitive bool) ([]b
|
||||
}
|
||||
|
||||
func (f *SLocalGuestFS) FilePutContents(sPath, content string, modAppend, caseInsensitive bool) error {
|
||||
sFilePath := f.getLocalPath(sPath, caseInsensitive)
|
||||
sFilePath := f.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sFilePath) > 0 {
|
||||
sPath = sFilePath
|
||||
} else {
|
||||
dirPath := f.getLocalPath(path.Dir(sPath), caseInsensitive)
|
||||
dirPath := f.GetLocalPath(path.Dir(sPath), caseInsensitive)
|
||||
if len(dirPath) > 0 {
|
||||
sPath = path.Join(dirPath, path.Base(sPath))
|
||||
}
|
||||
|
||||
@@ -69,15 +69,15 @@ func (p *SSHPartition) osMkdirP(dir string, mode uint32) error {
|
||||
func (p *SSHPartition) Mkdir(sPath string, mode int, caseInsensitive bool) error {
|
||||
segs := strings.Split(sPath, "/")
|
||||
sp := ""
|
||||
pPath := p.getLocalPath("/", caseInsensitive)
|
||||
pPath := p.GetLocalPath("/", caseInsensitive)
|
||||
var err error
|
||||
for _, s := range segs {
|
||||
if len(s) > 0 {
|
||||
sp = path.Join(sp, s)
|
||||
vPath := p.getLocalPath(sp, caseInsensitive)
|
||||
vPath := p.GetLocalPath(sp, caseInsensitive)
|
||||
if len(vPath) == 0 {
|
||||
err = p.osMkdirP(path.Join(pPath, s), uint32(mode))
|
||||
pPath = p.getLocalPath(sp, caseInsensitive)
|
||||
pPath = p.GetLocalPath(sp, caseInsensitive)
|
||||
} else {
|
||||
pPath = vPath
|
||||
}
|
||||
@@ -160,7 +160,7 @@ func (p *SSHPartition) IsMounted() bool {
|
||||
}
|
||||
|
||||
func (p *SSHPartition) Chmod(sPath string, mode uint32, caseI bool) error {
|
||||
sPath = p.getLocalPath(sPath, caseI)
|
||||
sPath = p.GetLocalPath(sPath, caseI)
|
||||
if sPath != "" {
|
||||
return p.osChmod(sPath, mode)
|
||||
}
|
||||
@@ -193,7 +193,7 @@ func (p *SSHPartition) osListDir(path string) ([]string, error) {
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (p *SSHPartition) getLocalPath(sPath string, caseI bool) string {
|
||||
func (p *SSHPartition) GetLocalPath(sPath string, caseI bool) string {
|
||||
var fullPath = p.mountPath
|
||||
pathSegs := strings.Split(sPath, "/")
|
||||
for _, seg := range pathSegs {
|
||||
@@ -221,7 +221,7 @@ func (p *SSHPartition) getLocalPath(sPath string, caseI bool) string {
|
||||
}
|
||||
|
||||
func (p *SSHPartition) Exists(sPath string, caseInsensitive bool) bool {
|
||||
sPath = p.getLocalPath(sPath, caseInsensitive)
|
||||
sPath = p.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
return p.osPathExists(sPath)
|
||||
}
|
||||
@@ -242,7 +242,7 @@ func (p *SSHPartition) sshFileGetContents(path string) ([]byte, error) {
|
||||
}
|
||||
|
||||
func (p *SSHPartition) FileGetContents(sPath string, caseInsensitive bool) ([]byte, error) {
|
||||
sPath = p.getLocalPath(sPath, caseInsensitive)
|
||||
sPath = p.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
return p.sshFileGetContents(sPath)
|
||||
}
|
||||
@@ -282,11 +282,11 @@ func (p *SSHPartition) sshFilePutContents(sPath, content string, modAppend bool)
|
||||
}
|
||||
|
||||
func (p *SSHPartition) FilePutContents(sPath, content string, modAppend, caseInsensitive bool) error {
|
||||
sFilePath := p.getLocalPath(sPath, caseInsensitive)
|
||||
sFilePath := p.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sFilePath) > 0 {
|
||||
sPath = sFilePath
|
||||
} else {
|
||||
dirPath := p.getLocalPath(path.Dir(sPath), caseInsensitive)
|
||||
dirPath := p.GetLocalPath(path.Dir(sPath), caseInsensitive)
|
||||
if len(dirPath) > 0 {
|
||||
sPath = path.Join(dirPath, path.Base(sPath))
|
||||
}
|
||||
@@ -298,7 +298,7 @@ func (p *SSHPartition) FilePutContents(sPath, content string, modAppend, caseIns
|
||||
}
|
||||
|
||||
func (p *SSHPartition) ListDir(sPath string, caseInsensitive bool) []string {
|
||||
sPath = p.getLocalPath(sPath, caseInsensitive)
|
||||
sPath = p.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
ret, err := p.osListDir(sPath)
|
||||
if err != nil {
|
||||
@@ -317,7 +317,7 @@ func (p *SSHPartition) osChown(sPath string, uid, gid int) error {
|
||||
}
|
||||
|
||||
func (p *SSHPartition) Chown(sPath string, uid, gid int, caseInsensitive bool) error {
|
||||
sPath = p.getLocalPath(sPath, caseInsensitive)
|
||||
sPath = p.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sPath) == 0 {
|
||||
return fmt.Errorf("Can't get local path: %s", sPath)
|
||||
}
|
||||
@@ -331,7 +331,7 @@ func (p *SSHPartition) osRemove(sPath string) error {
|
||||
}
|
||||
|
||||
func (p *SSHPartition) Remove(sPath string, caseInsensitive bool) {
|
||||
sPath = p.getLocalPath(sPath, caseInsensitive)
|
||||
sPath = p.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sPath) > 0 {
|
||||
p.osRemove(sPath)
|
||||
}
|
||||
@@ -445,7 +445,7 @@ func (info sFileInfo) Sys() interface{} {
|
||||
}
|
||||
|
||||
func (p *SSHPartition) Stat(sPath string, caseInsensitive bool) os.FileInfo {
|
||||
sPath = p.getLocalPath(sPath, caseInsensitive)
|
||||
sPath = p.GetLocalPath(sPath, caseInsensitive)
|
||||
if len(sPath) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -291,7 +291,9 @@ func (m *SGuestManager) GuestDeploy(ctx context.Context, params interface{}) (js
|
||||
password = seclib.RandomPassword(12)
|
||||
}
|
||||
|
||||
guestInfo, err := guest.DeployFs(guestfs.NewDeployInfo(publicKey, deploys, password, deployParams.IsInit, false, options.HostOptions.LinuxDefaultRootUser))
|
||||
guestInfo, err := guest.DeployFs(guestfs.NewDeployInfo(
|
||||
publicKey, deploys, password, deployParams.IsInit, false,
|
||||
options.HostOptions.LinuxDefaultRootUser, options.HostOptions.WindowsDefaultAdminUser))
|
||||
if err != nil {
|
||||
log.Errorf("Deploy guest fs error: %s", err)
|
||||
return nil, err
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/util/qemutils"
|
||||
"yunion.io/x/onecloud/pkg/util/sysutils"
|
||||
"yunion.io/x/onecloud/pkg/util/timeutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/winutils"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -216,8 +217,9 @@ func (h *SHostInfo) prepareEnv() error {
|
||||
log.Errorf("Failed to activate nbd device: %s", output)
|
||||
}
|
||||
|
||||
// TODO: winRegTool还未实现
|
||||
// if not WinRegTool.check_tool(options.chntpw_path)...
|
||||
if !winutils.CheckTool(options.HostOptions.ChntpwPath) {
|
||||
return fmt.Errorf("Failed to find chntpw tool")
|
||||
}
|
||||
|
||||
if err := hostbridge.Prepare(options.HostOptions.BridgeDriver); err != nil {
|
||||
log.Errorln(err)
|
||||
|
||||
@@ -44,7 +44,7 @@ func Init() {
|
||||
|
||||
func Start() {
|
||||
if hostMetricsCollector != nil {
|
||||
hostMetricsCollector.Start()
|
||||
go hostMetricsCollector.Start()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,8 @@ type SHostOptions struct {
|
||||
SnapshotDirSuffix string `help:"Snapshot dir name equal diskId concat snapshot dir suffix" default:"_snap"`
|
||||
SnapshotRecycleDay int `default:"1" help:"Snapshot Recycle delete Duration day"`
|
||||
|
||||
EnableTelegraf bool `default:"true" help:"enable send monitoring data to telegraf"`
|
||||
EnableTelegraf bool `default:"true" help:"enable send monitoring data to telegraf"`
|
||||
WindowsDefaultAdminUser bool `default:"true" help:"Default account for Windows system is Administrator"`
|
||||
}
|
||||
|
||||
var HostOptions SHostOptions
|
||||
|
||||
@@ -0,0 +1,683 @@
|
||||
package winutils
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
"yunion.io/x/onecloud/pkg/util/regutils2"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
var _CHNTPW_PATH string
|
||||
|
||||
func SetChntpwPath(spath string) {
|
||||
_CHNTPW_PATH = spath
|
||||
}
|
||||
|
||||
func GetChntpwPath() string {
|
||||
if len(_CHNTPW_PATH) == 0 {
|
||||
_CHNTPW_PATH = "/usr/local/bin/chntpw.static"
|
||||
}
|
||||
return _CHNTPW_PATH
|
||||
}
|
||||
|
||||
const (
|
||||
SYSTEM = "system"
|
||||
SOFTWARE = "software"
|
||||
SECURITY = "security"
|
||||
SAM = "sam"
|
||||
CONFIRM = "y"
|
||||
)
|
||||
|
||||
func NewWinRegTool(spath string) *SWinRegTool {
|
||||
return &SWinRegTool{ConfigPath: spath}
|
||||
}
|
||||
|
||||
func CheckTool(spath string) bool {
|
||||
if fileutils2.Exists(spath) && exec.Command(spath, "-h").Run() == nil {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
type SWinRegTool struct {
|
||||
ConfigPath string
|
||||
SystemPath string
|
||||
SoftwarePath string
|
||||
SamPath string
|
||||
SecurityPath string
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) CheckPath() bool {
|
||||
files, err := ioutil.ReadDir(w.ConfigPath)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
switch strings.ToLower(file.Name()) {
|
||||
case SYSTEM:
|
||||
w.SystemPath = path.Join(w.ConfigPath, file.Name())
|
||||
case SOFTWARE:
|
||||
w.SoftwarePath = path.Join(w.ConfigPath, file.Name())
|
||||
case SAM:
|
||||
w.SamPath = path.Join(w.ConfigPath, file.Name())
|
||||
case SECURITY:
|
||||
w.SecurityPath = path.Join(w.ConfigPath, file.Name())
|
||||
}
|
||||
}
|
||||
if len(w.SystemPath) > 0 && len(w.SoftwarePath) > 0 &&
|
||||
len(w.SamPath) > 0 && len(w.SecurityPath) > 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetUsers() map[string]bool {
|
||||
output, err := procutils.NewCommand(GetChntpwPath(), "-l", w.SamPath).Run()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
users := map[string]bool{}
|
||||
re := regexp.MustCompile(
|
||||
`\|\s*\w+\s*\|\s*(?P<user>\w+)\s*\|\s*(ADMIN)?\s*\|\s*(?P<lock>(dis/lock|\*BLANK\*)?)`)
|
||||
for _, line := range strings.Split(string(output), "\n") {
|
||||
m := regutils2.GetParams(re, line)
|
||||
if len(m) > 0 {
|
||||
user, _ := m["user"]
|
||||
if strings.ToLower(user) != "guest" {
|
||||
lock, _ := m["lock"]
|
||||
users[user] = lock != "dis/lock"
|
||||
}
|
||||
}
|
||||
}
|
||||
return users
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) samChange(user string, seq ...string) error {
|
||||
proc := exec.Command(GetChntpwPath(), "-u", user, w.SamPath, w.SystemPath, w.SecurityPath)
|
||||
stdin, err := proc.StdinPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer stdin.Close()
|
||||
|
||||
outb, err := proc.StdoutPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outb.Close()
|
||||
|
||||
errb, err := proc.StderrPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer errb.Close()
|
||||
|
||||
if err := proc.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
io.WriteString(stdin, "n\n")
|
||||
for _, s := range seq {
|
||||
io.WriteString(stdin, s+"\n")
|
||||
}
|
||||
io.WriteString(stdin, CONFIRM+"\n")
|
||||
stdoutPut, err := ioutil.ReadAll(outb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
stderrOutPut, err := ioutil.ReadAll(errb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Debugf("Sam change %s %s", stdoutPut, stderrOutPut)
|
||||
if proc.ProcessState.Exited() {
|
||||
if err := proc.Wait(); err != nil {
|
||||
if exiterr, ok := err.(*exec.ExitError); ok {
|
||||
ws := exiterr.Sys().(syscall.WaitStatus)
|
||||
if ws.ExitStatus() == 2 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
log.Errorf("Failed to change SAM password")
|
||||
return err
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
proc.Process.Kill()
|
||||
return fmt.Errorf("Failed to change SAM password, not exit cleanly")
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) ChangePassword(user, password string) error {
|
||||
return w.samChange(user, "2", password)
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) RemovePassword(user string) error {
|
||||
return w.samChange(user, "2")
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) UnlockUser(user string) error {
|
||||
return w.samChange(user, "4")
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetRegFile(regPath string) (string, []string) {
|
||||
re := regexp.MustCompile("\\")
|
||||
vals := re.Split(regPath, -1)
|
||||
regSeg := []string{}
|
||||
for _, val := range vals {
|
||||
if len(val) > 0 {
|
||||
regSeg = append(regSeg, val)
|
||||
}
|
||||
}
|
||||
|
||||
if regSeg[0] == "HKLM" {
|
||||
regSeg = regSeg[1:]
|
||||
}
|
||||
if strings.ToLower(regSeg[0]) == SOFTWARE {
|
||||
regSeg = regSeg[1:]
|
||||
return w.SoftwarePath, regSeg
|
||||
} else if strings.ToLower(regSeg[0]) == SYSTEM {
|
||||
regSeg = regSeg[1:]
|
||||
return w.SystemPath, regSeg
|
||||
} else {
|
||||
return "", nil
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) showRegistry(spath string, keySeg []string, verb string) ([]string, error) {
|
||||
proc := exec.Command(GetChntpwPath(), spath)
|
||||
stdin, err := proc.StdinPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer stdin.Close()
|
||||
|
||||
outb, err := proc.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer outb.Close()
|
||||
|
||||
// errb, err := proc.StderrPipe()
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// defer errb.Close()
|
||||
|
||||
if err := proc.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keypath := strings.Join(keySeg, "\\")
|
||||
io.WriteString(stdin, fmt.Sprintf("%s %s\n", verb, keypath))
|
||||
io.WriteString(stdin, "q\n")
|
||||
stdoutPut, err := ioutil.ReadAll(outb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !proc.ProcessState.Exited() {
|
||||
proc.Process.Kill()
|
||||
}
|
||||
return strings.Split(string(stdoutPut), "\n"), nil
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) getRegistry(spath string, keySeg []string) string {
|
||||
keyPath := strings.Join(keySeg, "\\")
|
||||
lines, err := w.showRegistry(spath, keySeg, "cat")
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return ""
|
||||
}
|
||||
for i, line := range lines {
|
||||
if len(keyPath) > 85 {
|
||||
keyPath = keyPath[:85]
|
||||
}
|
||||
if strings.Contains(line, fmt.Sprintf("> Value <%s> of type REG_", keyPath)) {
|
||||
return lines[i+1]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type sRegistry struct {
|
||||
Key string
|
||||
Type string
|
||||
Size string
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) listRegistry(spath string, keySeg []string) ([]string, []sRegistry, error) {
|
||||
lines, err := w.showRegistry(spath, keySeg, "ls")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
keys := []string{}
|
||||
values := []sRegistry{}
|
||||
keyPattern := regexp.MustCompile("^<(?P<key>[^>]+)>$")
|
||||
valPattern := regexp.MustCompile(`^(?P<size>\d+)\s+(?P<type>REG\_\w+)\s+<(?P<key>[^>]+)>\s*`)
|
||||
for _, line := range lines {
|
||||
m := regutils2.GetParams(keyPattern, line)
|
||||
if len(m) > 0 {
|
||||
keys = append(keys, m["key"])
|
||||
}
|
||||
m = regutils2.GetParams(valPattern, line)
|
||||
if len(m) > 0 {
|
||||
values = append(values, sRegistry{m["key"], m["type"], m["size"]})
|
||||
}
|
||||
}
|
||||
|
||||
return keys, values, nil
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) cmdRegistry(spath string, ops []string, retcode int) bool {
|
||||
proc := exec.Command(GetChntpwPath(), "-e", spath)
|
||||
stdin, err := proc.StdinPipe()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return false
|
||||
}
|
||||
defer stdin.Close()
|
||||
|
||||
outb, err := proc.StdoutPipe()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return false
|
||||
}
|
||||
defer outb.Close()
|
||||
|
||||
errb, err := proc.StderrPipe()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return false
|
||||
}
|
||||
defer errb.Close()
|
||||
|
||||
if err := proc.Start(); err != nil {
|
||||
log.Errorln(err)
|
||||
return false
|
||||
}
|
||||
|
||||
for _, op := range ops {
|
||||
io.WriteString(stdin, op+"\n")
|
||||
}
|
||||
io.WriteString(stdin, "q\n")
|
||||
io.WriteString(stdin, CONFIRM+"\n")
|
||||
stdoutPut, err := ioutil.ReadAll(outb)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return false
|
||||
}
|
||||
stderrOutPut, err := ioutil.ReadAll(errb)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return false
|
||||
}
|
||||
log.Debugf("Cmd registry %s %s", stdoutPut, stderrOutPut)
|
||||
if proc.ProcessState.Exited() {
|
||||
if err := proc.Wait(); err != nil {
|
||||
if exiterr, ok := err.(*exec.ExitError); ok {
|
||||
ws := exiterr.Sys().(syscall.WaitStatus)
|
||||
if ws.ExitStatus() == retcode {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return retcode == 0
|
||||
}
|
||||
} else {
|
||||
proc.Process.Kill()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) setRegistry(spath string, keySeg []string, value string) bool {
|
||||
keyPath := strings.Join(keySeg, "\\")
|
||||
return w.cmdRegistry(spath, []string{fmt.Sprintf("ed %s", keyPath), value}, 0)
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) mkdir(spath string, keySeg []string) bool {
|
||||
return w.cmdRegistry(spath,
|
||||
[]string{
|
||||
fmt.Sprintf("cd %s", strings.Join(keySeg[:len(keySeg)-1], "\\")),
|
||||
fmt.Sprintf("nk %s", keySeg[len(keySeg)-1]),
|
||||
}, 2)
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) keyExists(spath string, keySeg []string) bool {
|
||||
keys, _, err := w.listRegistry(spath, keySeg[:len(keySeg)-1])
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return false
|
||||
}
|
||||
if utils.IsInStringArray(keySeg[len(keySeg)-1], keys) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) valExists(spath string, keySeg []string) bool {
|
||||
_, vals, err := w.listRegistry(spath, keySeg[:len(keySeg)-1])
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return false
|
||||
}
|
||||
for _, val := range vals {
|
||||
if val.Key == keySeg[len(keySeg)-1] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) mkdir_P(spath string, keySeg []string) bool {
|
||||
seg := []string{}
|
||||
for _, k := range keySeg {
|
||||
seg = append(seg, k)
|
||||
if !w.keyExists(spath, seg) {
|
||||
if !w.mkdir(spath, seg) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) newValue(spath string, keySeg []string, regtype, val string) bool {
|
||||
REG_TYPE_TBL := []string{
|
||||
"REG_NONE",
|
||||
"REG_SZ",
|
||||
"REG_EXPAND_SZ",
|
||||
"REG_BINARY",
|
||||
"REG_DWORD",
|
||||
"REG_DWORD_BIG_ENDIAN",
|
||||
"REG_LINK",
|
||||
"REG_MULTI_SZ",
|
||||
"REG_RESOUCE_LIST",
|
||||
"REG_FULL_RES_DESC",
|
||||
"REG_RES_REQ",
|
||||
"REG_QWORD",
|
||||
}
|
||||
|
||||
ok, idx := utils.InStringArray(regtype, REG_TYPE_TBL)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
cmds := []string{
|
||||
fmt.Sprintf("cd %s", strings.Join(keySeg[:len(keySeg)-1], "\\")),
|
||||
fmt.Sprintf("nv %x %s", idx, keySeg[len(keySeg)-1]),
|
||||
fmt.Sprintf("ed %s", keySeg[len(keySeg)-1]),
|
||||
}
|
||||
|
||||
if regtype == "REG_QWORD" {
|
||||
cmds = append(cmds, "16", ": 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0", "s")
|
||||
} else {
|
||||
cmds = append(cmds, val)
|
||||
}
|
||||
return w.cmdRegistry(spath, cmds, 0)
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetRegistry(keyPath string) string {
|
||||
p1, p2s := w.GetRegFile(keyPath)
|
||||
if len(p1) == 0 && len(p2s) == 0 {
|
||||
return ""
|
||||
} else {
|
||||
return w.getRegistry(p1, p2s)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) ListRegistry(keyPath string) ([]string, []sRegistry) {
|
||||
p1, p2s := w.GetRegFile(keyPath)
|
||||
if len(p1) == 0 && len(p2s) == 0 {
|
||||
return nil, nil
|
||||
} else {
|
||||
v1, v2, err := w.listRegistry(p1, p2s)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return nil, nil
|
||||
}
|
||||
return v1, v2
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) SetRegistry(keyPath, value, regtype string) bool {
|
||||
p1, p2s := w.GetRegFile(keyPath)
|
||||
if len(p1) == 0 && len(p2s) == 0 {
|
||||
return false
|
||||
} else {
|
||||
if w.valExists(p1, p2s) {
|
||||
return w.setRegistry(p1, p2s, value)
|
||||
} else {
|
||||
if !w.keyExists(p1, p2s[:len(p2s)-1]) {
|
||||
if !w.mkdir_P(p1, p2s[:len(p2s)-1]) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return w.newValue(p1, p2s, regtype, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) KeyExists(keyPath string) bool {
|
||||
p1, p2s := w.GetRegFile(keyPath)
|
||||
if len(p1) == 0 && len(p2s) == 0 {
|
||||
return false
|
||||
} else {
|
||||
return w.keyExists(p1, p2s)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) MkdirP(keyPath string) bool {
|
||||
p1, p2s := w.GetRegFile(keyPath)
|
||||
if len(p1) == 0 && len(p2s) == 0 {
|
||||
return false
|
||||
} else {
|
||||
return w.mkdir_P(p1, p2s)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetCcsKey() string {
|
||||
ver := w.GetRegistry(`HKLM\SYSTEM\Select\Current`)
|
||||
iv, _ := strconv.ParseInt(ver, 16, 0)
|
||||
return fmt.Sprintf("ControlSet%03d", iv)
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetCcsKeyPath() string {
|
||||
return fmt.Sprintf(`HKLM\SYSTEM\%s`, w.GetCcsKey())
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) getComputerNameKeyPath() string {
|
||||
key := w.GetCcsKey()
|
||||
return key + `\Control\ComputerName\ComputerName\ComputerName`
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetComputerName() string {
|
||||
key := w.getComputerNameKeyPath()
|
||||
return w.GetRegistry(key)
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) setComputerName(cn string) {
|
||||
MAX_COMPUTER_NAME_LEN := 15
|
||||
COMMON_PREFIX_LEN := 10
|
||||
if len(cn) > MAX_COMPUTER_NAME_LEN {
|
||||
suffix := cn[COMMON_PREFIX_LEN:]
|
||||
suffixlen := MAX_COMPUTER_NAME_LEN - COMMON_PREFIX_LEN
|
||||
md5sum := md5.Sum([]byte(suffix))
|
||||
cn = cn[:COMMON_PREFIX_LEN] + string(md5sum[:])[:suffixlen]
|
||||
}
|
||||
key := w.getComputerNameKeyPath()
|
||||
w.SetRegistry(key, cn, "")
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) SetHostname(hostname, domain string) {
|
||||
tcpipKey := w.GetCcsKeyPath() + `\Services\Tcpip\Parameters`
|
||||
hnKey := tcpipKey + `\Hostname`
|
||||
dmKey := tcpipKey + `\Domain`
|
||||
nvHnKey := tcpipKey + `\NV Hostname`
|
||||
nvDmKey := tcpipKey + `\NV Domain`
|
||||
w.SetRegistry(hnKey, hostname, "REG_SZ")
|
||||
w.SetRegistry(dmKey, domain, "REG_SZ")
|
||||
w.SetRegistry(nvHnKey, hostname, "REG_SZ")
|
||||
w.SetRegistry(nvDmKey, domain, "REG_SZ")
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) SetDnsServer(nameserver, searchlist string) {
|
||||
tcpipKey := w.GetCcsKeyPath() + `\Services\Tcpip\Parameters`
|
||||
ns_key := tcpipKey + `\NameServer`
|
||||
search_key := tcpipKey + `\SearchList`
|
||||
w.SetRegistry(ns_key, nameserver, "REG_SZ")
|
||||
w.SetRegistry(search_key, searchlist, "REG_SZ")
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetProductName() string {
|
||||
prodKey := `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName`
|
||||
return w.GetRegistry(prodKey)
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetVersion() string {
|
||||
prodKey := `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion`
|
||||
return w.GetRegistry(prodKey)
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetInstallLanguage() string {
|
||||
nlsTbl := map[string]string{"0804": "zh_CN", "0404": "zh_TW", "0c04": "zh_HK",
|
||||
"1004": "zh_SG", "0409": "en_US", "0809": "en_UK"}
|
||||
key := w.GetCcsKeyPath()
|
||||
key += `\Control\Nls\Language\InstallLanguage`
|
||||
val := w.GetRegistry(key)
|
||||
if xval, ok := nlsTbl[key]; ok {
|
||||
return xval
|
||||
} else {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetArch() string {
|
||||
prodKey := `HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\CurrentVersion`
|
||||
ver := w.GetRegistry(prodKey)
|
||||
if len(ver) > 0 {
|
||||
return "x86_64"
|
||||
} else {
|
||||
return "x86"
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) LogontypePath() string {
|
||||
return `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\LogonType`
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetLogontype() string {
|
||||
return w.GetRegistry(w.LogontypePath())
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) SetLogontype(val string) {
|
||||
w.SetRegistry(w.LogontypePath(), val, "")
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) DefaultAccountPath() string {
|
||||
return `HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName`
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetDefaultAccount() string {
|
||||
return w.GetRegistry(w.DefaultAccountPath())
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) SetDefaultAccount(user string) {
|
||||
w.SetRegistry(w.DefaultAccountPath(), user, "")
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GpeditScriptPath() string {
|
||||
return `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\Scripts`
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GpeditScriptStatePath() string {
|
||||
return `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\Scripts`
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetGpeditStartScripts() []string {
|
||||
scriptKey := w.GpeditScriptPath() + `\Startup\0`
|
||||
keys, _ := w.ListRegistry(scriptKey)
|
||||
ret := []string{}
|
||||
for _, k := range keys {
|
||||
spath := scriptKey + (fmt.Sprintf(`\%s\Script`, k))
|
||||
val := w.GetRegistry(spath)
|
||||
ret = append(ret, val)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) IsGpeditStartScriptInstalled(script string) bool {
|
||||
scripts := w.GetGpeditStartScripts()
|
||||
return utils.IsInStringArray(script, scripts)
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) InstallGpeditStartScript(script string) {
|
||||
if w.IsGpeditStartScriptInstalled(script) {
|
||||
return
|
||||
}
|
||||
w.installGpeditStartScript(script, w.GpeditScriptPath())
|
||||
w.installGpeditStartScript(script, w.GpeditScriptStatePath())
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) GetGpoDisplayname() string {
|
||||
spath := `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine\GPO-List\0\DisplayName`
|
||||
return w.GetRegistry(spath)
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) installGpeditStartScript(script, scriptPath string) {
|
||||
idx := 0
|
||||
if !w.KeyExists(scriptPath + `\Startup`) {
|
||||
w.MkdirP(scriptPath + `\Startup`)
|
||||
w.MkdirP(scriptPath + `\Shutdown`)
|
||||
dsname := "Local Group Policy"
|
||||
kvts := [][3]string{
|
||||
[3]string{"GPO-ID", "LocalGPO", "REG_SZ"},
|
||||
[3]string{"SOM-ID", "Local", "REG_SZ"},
|
||||
[3]string{"FileSysPath", `C:\Windows\System32\GroupPolicy\Machine`, "REG_SZ"},
|
||||
[3]string{"DisplayName", dsname, "REG_SZ"},
|
||||
[3]string{"GPOName", dsname, "REG_SZ"},
|
||||
[3]string{"PSScriptOrder", "1", "REG_DWORD"},
|
||||
}
|
||||
for _, kvt := range kvts {
|
||||
w.SetRegistry(fmt.Sprintf(`%s\Startup\0\%s`, scriptPath, kvt[0]), kvt[1], kvt[2])
|
||||
}
|
||||
|
||||
} else {
|
||||
for w.KeyExists(scriptPath + (fmt.Sprintf(`\Startup\0\%d`, idx))) {
|
||||
idx += 1
|
||||
}
|
||||
}
|
||||
|
||||
kvts := [][3]string{
|
||||
[3]string{"Script", script, "REG_SZ"},
|
||||
[3]string{"Parameters", "", "REG_SZ"},
|
||||
[3]string{"ExecTime", "", "REG_QWORD"},
|
||||
[3]string{"IsPowershell", "0", "REG_DWORD"},
|
||||
}
|
||||
for _, kvt := range kvts {
|
||||
w.SetRegistry(fmt.Sprintf(`%s\Startup\0\%d\%s`, scriptPath, idx, kvt[0]), kvt[1], kvt[2])
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SWinRegTool) EnableRdp() {
|
||||
key := w.GetCcsKeyPath() + `\Control\Terminal Server\fDenyTSConnections`
|
||||
w.SetRegistry(key, "0", `REG_DWORD`)
|
||||
key = w.GetCcsKeyPath() + `\Services\MpsSvc\Start`
|
||||
w.SetRegistry(key, "3", `REG_DWORD`)
|
||||
}
|
||||
Reference in New Issue
Block a user