-
Notifications
You must be signed in to change notification settings - Fork 1
/
winrm.go
89 lines (78 loc) · 2.56 KB
/
winrm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package services
import (
"errors"
"fmt"
"net"
"strconv"
"strings"
"time"
"github.com/ScoreTrak/ScoreTrak/pkg/exec"
"github.com/masterzen/winrm"
)
type Winrm struct {
Username string
Password string
Port string
Command string
ExpectedOutput string
Scheme string
ClientType string
}
func NewWinrm() *Winrm {
return &Winrm{Command: "whoami", Scheme: "http", ClientType: "NTLM"}
}
var ErrWinrmRequiresUsernameAndPassword = errors.New("winrm check_service needs username, and password")
func (w *Winrm) Validate() error {
if w.Password != "" && w.Username != "" {
return nil
}
return ErrWinrmRequiresUsernameAndPassword
}
func (w *Winrm) Execute(e exec.Exec) (passed bool, logOutput string, err error) {
isHTTPS := IsSecure(w.Scheme)
if w.Port == "" {
if isHTTPS {
w.Port = "5986"
} else {
w.Port = "5985"
}
}
i, err := strconv.Atoi(w.Port)
if err != nil {
return false, "", fmt.Errorf("unable to convert port number to integer: %w", err)
}
err = tcpPortDial(net.JoinHostPort(e.Host, w.Port), time.Until(e.Deadline())/3)
if err != nil {
return false, "", err
}
endpoint := winrm.NewEndpoint(e.Host, i, isHTTPS, true, nil, nil, nil, time.Until(e.Deadline()))
params := winrm.DefaultParameters
params.Dial = (&net.Dialer{
Timeout: time.Until(e.Deadline()),
}).Dial
if strings.ToLower(w.ClientType) == "ntlm" {
params.TransportDecorator = func() winrm.Transporter { return &winrm.ClientNTLM{} }
}
client, err := winrm.NewClientWithParameters(endpoint, w.Username, w.Password, params)
if err != nil {
return false, "", fmt.Errorf("unable to initialize winrm client: %w", err)
}
procStdout, procStderr, returnCode, err := client.RunWithString(w.Command, "")
if err != nil {
return false, "", fmt.Errorf("unable to execute provided command: %w", err)
}
if returnCode != 0 {
return false, "", fmt.Errorf("%w: %s", ErrNonZeroReturn, procStderr)
}
if w.ExpectedOutput != "" && !strings.Contains(procStdout, strings.ToLower(w.ExpectedOutput)) {
return false, "", fmt.Errorf("%w. Output Received: %s", ErrDidNotMatchExpectedOutput, procStdout)
}
return true, Success, nil
}
var ErrNonZeroReturn = errors.New("process returned a non-zero code")
// endpoint := winrm.NewEndpoint(e.Host, i, isHttps, true, nil, nil, nil, time.Until(e.Deadline()))
// // params := winrm.NewParameters(strconv.Itoa(int(time.Until(e.Deadline()).Seconds()))+"S", "en-US", 153600)
// client, err := winrm.NewClient(endpoint, w.Username, w.Password)
// if err != nil {
// return false, "Unable to initialize winrm client", err
// }