agent/util/process/process_windows.go (130 lines of code) (raw):

package process import ( "errors" "fmt" "os" "syscall" "unsafe" "github.com/aliyun/aliyun_assist_client/agent/cryptdata" "github.com/aliyun/aliyun_assist_client/agent/log" "github.com/aliyun/aliyun_assist_client/agent/util/paramstore" "golang.org/x/sys/windows" ) var ( advapi32 = syscall.NewLazyDLL("advapi32.dll") logonProc = advapi32.NewProc("LogonUserW") impersonateProc = advapi32.NewProc("ImpersonateLoggedOnUser") revertSelfProc = advapi32.NewProc("RevertToSelf") ) const ( //logon32LogonNetwork = uintptr(3) logon32LOGONINTERACTIVE = uintptr(2) logon32ProviderDefault = uintptr(0) ) func (p *ProcessCmd) prepareProcess() error { // if p.command.SysProcAttr == nil { // p.command.SysProcAttr = &windows.SysProcAttr{} // } // 1. Duplicate current environment variable settings as base var env []string if p.command.Env == nil || len(p.command.Env) == 0 { env = os.Environ() } else { // append specific envs to osEnv, the value of repetitive key will be covered env = os.Environ() for i := 0; i < len(p.command.Env); i++ { env = append(env, p.command.Env[i]) } } p.command.Env = env for _, opt := range p.commandOptions { if err := opt(p.command); err != nil { return err } } return nil } func (p *ProcessCmd) addCredential() error { log.GetLogger().Infoln("addCredential") vm_password, err := getSecretParam(p.password) if err != nil { log.GetLogger().Errorln("get password failed", err) return err } token, err := logonUser(p.user_name, vm_password) if err != nil { return err } p.command.SysProcAttr = &windows.SysProcAttr{ Token: syscall.Token(token), } return nil } func (p *ProcessCmd) removeCredential() error { p.command.SysProcAttr.Token.Close() return nil } func impersonate(user string, pass string) error { token, err := logonUser(user, pass) if err != nil { return err } defer mustCloseHandle(token) if rc, _, ec := syscall.Syscall(impersonateProc.Addr(), 1, uintptr(token), 0, 0); rc == 0 { return error(ec) } return nil } func IsUserValid (userName string, password string) error { vm_password, err := getSecretParam(password) if err != nil { return err } token, err := logonUser(userName, vm_password) if err != nil { log.GetLogger().WithError(err).Errorf("Authentication failed for user %s with password", userName) return errors.New("UsernameOrPasswordInvalid") } defer mustCloseHandle(token) return nil } func logonUser(user, pass string) (token syscall.Handle, err error) { // ".\0" meaning "this computer: domain := [2]uint16{uint16('.'), 0} //domain,_ := syscall.UTF16FromString("") var pu, pp []uint16 if pu, err = syscall.UTF16FromString(user); err != nil { return } if pp, err = syscall.UTF16FromString(pass); err != nil { return } if rc, _, ec := syscall.Syscall6(logonProc.Addr(), 6, uintptr(unsafe.Pointer(&pu[0])), uintptr(unsafe.Pointer(&domain[0])), uintptr(unsafe.Pointer(&pp[0])), logon32LOGONINTERACTIVE, logon32ProviderDefault, uintptr(unsafe.Pointer(&token))); rc == 0 { err = error(ec) } return } func mustCloseHandle(handle syscall.Handle) { if err := syscall.CloseHandle(handle); err != nil { log.GetLogger().Errorln(err) } } //revertToSelf reverts the impersonation process. func revertToSelf() error { if rc, _, ec := syscall.Syscall(revertSelfProc.Addr(), 0, 0, 0, 0); rc == 0 { return error(ec) } return nil } func getSecretParam(secretName string) (string, error) { var value string var paramValueInfo *cryptdata.ParamValueInfo var err_1, err_2 error if paramValueInfo, err_1 = cryptdata.GetSecretParamValue(secretName); err_1 != nil { if value, err_2 = paramstore.GetSecretParam(secretName); err_2 != nil { log.GetLogger().Errorf("Secret param '%s' not found in agent [%v] and oos[%v]", secretName, err_1, err_2) err := errors.New(fmt.Sprintf("Secret param '%s' not found in agent [%v] and oos[%v]", secretName, err_1, err_2)) return "", err } } else { value = paramValueInfo.SecretValue } return value, nil }