aboutsummaryrefslogtreecommitdiff
path: root/internal/exec/tsch/tsch.go
diff options
context:
space:
mode:
authorBryan McNulty <bryanmcnulty@protonmail.com>2025-03-08 06:07:29 -0600
committerBryan McNulty <bryanmcnulty@protonmail.com>2025-03-08 06:07:29 -0600
commit7574b7370be083ff563fa8ad6d01d5ac776d7e4d (patch)
tree78aeb5d671e35aee8780fd92b2511cad00efd67d /internal/exec/tsch/tsch.go
parentd8eca7209d000609fea08d2973a402a41a4cf921 (diff)
downloadgoexec-7574b7370be083ff563fa8ad6d01d5ac776d7e4d.tar.gz
goexec-7574b7370be083ff563fa8ad6d01d5ac776d7e4d.zip
Add a bunch of DCE related options to TSCH module
Diffstat (limited to 'internal/exec/tsch/tsch.go')
-rw-r--r--internal/exec/tsch/tsch.go183
1 files changed, 112 insertions, 71 deletions
diff --git a/internal/exec/tsch/tsch.go b/internal/exec/tsch/tsch.go
index bc3ed0b..f2476f1 100644
--- a/internal/exec/tsch/tsch.go
+++ b/internal/exec/tsch/tsch.go
@@ -1,102 +1,143 @@
package tschexec
import (
- "encoding/xml"
+ "context"
+ "encoding/xml"
+ "fmt"
+ "github.com/oiweiwei/go-msrpc/msrpc/tsch/itaskschedulerservice/v1"
+ "github.com/rs/zerolog"
+)
+
+const (
+ TaskXMLDurationFormat = "2006-01-02T15:04:05.9999999Z"
+ TaskXMLHeader = `<?xml version="1.0" encoding="UTF-16"?>`
)
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/0d6383e4-de92-43e7-b0bb-a60cfa36379f
+type triggers struct {
+ XMLName xml.Name `xml:"Triggers"`
+ TimeTriggers []taskTimeTrigger `xml:"TimeTrigger,omitempty"`
+}
+
type taskTimeTrigger struct {
- XMLName xml.Name `xml:"TimeTrigger"`
- StartBoundary string `xml:"StartBoundary,omitempty"` // Derived from time.Time
- EndBoundary string `xml:"EndBoundary,omitempty"` // Derived from time.Time; must be > StartBoundary
- Enabled bool `xml:"Enabled"`
+ XMLName xml.Name `xml:"TimeTrigger"`
+ StartBoundary string `xml:"StartBoundary,omitempty"` // Derived from time.Time
+ EndBoundary string `xml:"EndBoundary,omitempty"` // Derived from time.Time; must be > StartBoundary
+ Enabled bool `xml:"Enabled"`
}
type idleSettings struct {
- StopOnIdleEnd bool `xml:"StopOnIdleEnd"`
- RestartOnIdle bool `xml:"RestartOnIdle"`
+ XMLName xml.Name `xml:"IdleSettings"`
+ StopOnIdleEnd bool `xml:"StopOnIdleEnd"`
+ RestartOnIdle bool `xml:"RestartOnIdle"`
}
type settings struct {
- XMLName xml.Name `xml:"Settings"`
- Enabled bool `xml:"Enabled"`
- Hidden bool `xml:"Hidden"`
- DisallowStartIfOnBatteries bool `xml:"DisallowStartIfOnBatteries"`
- StopIfGoingOnBatteries bool `xml:"StopIfGoingOnBatteries"`
- AllowHardTerminate bool `xml:"AllowHardTerminate"`
- RunOnlyIfNetworkAvailable bool `xml:"RunOnlyIfNetworkAvailable"`
- AllowStartOnDemand bool `xml:"AllowStartOnDemand"`
- WakeToRun bool `xml:"WakeToRun"`
- RunOnlyIfIdle bool `xml:"RunOnlyIfIdle"`
- StartWhenAvailable bool `xml:"StartWhenAvailable"`
- Priority int `xml:"Priority,omitempty"` // 1 to 10 inclusive
- MultipleInstancesPolicy string `xml:"MultipleInstancesPolicy,omitempty"`
- ExecutionTimeLimit string `xml:"ExecutionTimeLimit,omitempty"`
- DeleteExpiredTaskAfter string `xml:"DeleteExpiredTaskAfter,omitempty"` // Derived from time.Duration
- IdleSettings idleSettings `xml:"IdleSettings,omitempty"`
+ XMLName xml.Name `xml:"Settings"`
+ Enabled bool `xml:"Enabled"`
+ Hidden bool `xml:"Hidden"`
+ DisallowStartIfOnBatteries bool `xml:"DisallowStartIfOnBatteries"`
+ StopIfGoingOnBatteries bool `xml:"StopIfGoingOnBatteries"`
+ AllowHardTerminate bool `xml:"AllowHardTerminate"`
+ RunOnlyIfNetworkAvailable bool `xml:"RunOnlyIfNetworkAvailable"`
+ AllowStartOnDemand bool `xml:"AllowStartOnDemand"`
+ WakeToRun bool `xml:"WakeToRun"`
+ RunOnlyIfIdle bool `xml:"RunOnlyIfIdle"`
+ StartWhenAvailable bool `xml:"StartWhenAvailable"`
+ Priority int `xml:"Priority,omitempty"` // 1 to 10 inclusive
+ MultipleInstancesPolicy string `xml:"MultipleInstancesPolicy,omitempty"`
+ ExecutionTimeLimit string `xml:"ExecutionTimeLimit,omitempty"`
+ DeleteExpiredTaskAfter string `xml:"DeleteExpiredTaskAfter,omitempty"` // Derived from time.Duration
+ IdleSettings idleSettings `xml:"IdleSettings,omitempty"`
}
type actionExec struct {
- XMLName xml.Name `xml:"Exec"`
- Command string `xml:"Command"`
- Arguments string `xml:"Arguments"`
+ XMLName xml.Name `xml:"Exec"`
+ Command string `xml:"Command"`
+ Arguments string `xml:"Arguments"`
}
type actions struct {
- XMLName xml.Name `xml:"Actions"`
- Context string `xml:"Context,attr"`
- Exec []actionExec `xml:"Exec,omitempty"`
+ XMLName xml.Name `xml:"Actions"`
+ Context string `xml:"Context,attr"`
+ Exec []actionExec `xml:"Exec,omitempty"`
}
type principals struct {
- XMLName xml.Name `xml:"Principals"`
- Principals []principal `xml:"Principal"`
+ XMLName xml.Name `xml:"Principals"`
+ Principals []principal `xml:"Principal,omitempty"`
}
type principal struct {
- XMLName xml.Name `xml:"Principal"`
- ID string `xml:"id,attr"`
- UserID string `xml:"UserId"`
- RunLevel string `xml:"RunLevel"`
+ XMLName xml.Name `xml:"Principal"`
+ ID string `xml:"id,attr"`
+ UserID string `xml:"UserId"`
+ RunLevel string `xml:"RunLevel"`
}
type task struct {
- XMLName xml.Name `xml:"Task"`
- TaskVersion string `xml:"version,attr"`
- TaskNamespace string `xml:"xmlns,attr"`
- TimeTriggers []taskTimeTrigger `xml:"Triggers>TimeTrigger,omitempty"`
- Actions actions `xml:"Actions"`
- Principals principals `xml:"Principals"`
- Settings settings `xml:"Settings"`
+ XMLName xml.Name `xml:"Task"`
+ TaskVersion string `xml:"version,attr"`
+ TaskNamespace string `xml:"xmlns,attr"`
+ //TimeTriggers []taskTimeTrigger `xml:"Triggers>TimeTrigger,omitempty"` // TODO: triggers type
+ Triggers triggers `xml:"Triggers"`
+ Actions actions `xml:"Actions"`
+ Principals principals `xml:"Principals"`
+ Settings settings `xml:"Settings"`
}
-var (
- defaultSettings = settings{
- MultipleInstancesPolicy: "IgnoreNew",
- DisallowStartIfOnBatteries: false,
- StopIfGoingOnBatteries: false,
- AllowHardTerminate: true,
- RunOnlyIfNetworkAvailable: false,
- IdleSettings: idleSettings{
- StopOnIdleEnd: true,
- RestartOnIdle: false,
- },
- AllowStartOnDemand: true,
- Enabled: true,
- Hidden: true,
- RunOnlyIfIdle: false,
- WakeToRun: false,
- Priority: 7, // 7 is a pretty standard value for scheduled tasks
- StartWhenAvailable: true,
- }
- defaultPrincipals = principals{
- Principals: []principal{
- {
- ID: "SYSTEM",
- UserID: "S-1-5-18",
- RunLevel: "HighestAvailable",
- },
- },
- }
-)
+// registerTask serializes and submits the provided task structure
+func (mod *Module) registerTask(ctx context.Context, taskDef task, taskPath string) (path string, err error) {
+
+ var taskXml string
+
+ log := zerolog.Ctx(ctx).With().
+ Str("module", "tsch").
+ Str("func", "createTask").Logger()
+
+ // Generate task XML content. See https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-tsch/0d6383e4-de92-43e7-b0bb-a60cfa36379f
+ {
+ doc, err := xml.Marshal(taskDef)
+ if err != nil {
+ log.Error().Err(err).Msg("failed to marshal task XML")
+ return "", fmt.Errorf("marshal task: %w", err)
+ }
+ taskXml = TaskXMLHeader + string(doc)
+ log.Debug().Str("content", taskXml).Msg("Generated task XML")
+ }
+
+ // Submit task
+ {
+ response, err := mod.tsch.RegisterTask(ctx, &itaskschedulerservice.RegisterTaskRequest{
+ Path: taskPath,
+ XML: taskXml,
+ Flags: 0, // TODO
+ LogonType: 0, // TASK_LOGON_NONE
+ CredsCount: 0,
+ Creds: nil,
+ })
+ if err != nil {
+ log.Error().Err(err).Msg("Failed to register task")
+ return "", fmt.Errorf("register task: %w", err)
+ }
+ log.Info().Str("path", taskPath).Msg("Task created successfully")
+ path = response.ActualPath
+ }
+ return
+}
+
+func (mod *Module) deleteTask(ctx context.Context, taskPath string) (err error) {
+
+ log := zerolog.Ctx(ctx).With().
+ Str("module", "tsch").
+ Str("path", taskPath).
+ Str("func", "deleteTask").Logger()
+
+ if _, err = mod.tsch.Delete(ctx, &itaskschedulerservice.DeleteRequest{Path: taskPath}); err != nil {
+ log.Error().Err(err).Msg("Failed to delete task")
+ return fmt.Errorf("delete task: %w", err)
+ }
+ log.Info().Msg("Task deleted successfully")
+ return
+}