1
0

feat: initial daemon implementation

This commit is contained in:
2024-02-20 13:25:31 +00:00
parent 820208d079
commit 0314b5ca93
45 changed files with 2989 additions and 1041 deletions

View File

@ -5,214 +5,14 @@
package config
import (
"fmt"
"io/ioutil"
"io"
"os"
"regexp"
"strings"
"time"
"code.dumpstack.io/tools/out-of-tree/distro"
"github.com/naoina/toml"
)
type Kernel struct {
// TODO
// Version string
// From string
// To string
// prev. ReleaseMask
Regex string
ExcludeRegex string
}
// Target defines the kernel
type Target struct {
Distro distro.Distro
Kernel Kernel
}
// DockerName is returns stable name for docker container
func (km Target) DockerName() string {
distro := strings.ToLower(km.Distro.ID.String())
release := strings.Replace(km.Distro.Release, ".", "__", -1)
return fmt.Sprintf("out_of_tree_%s_%s", distro, release)
}
// ArtifactType is the kernel module or exploit
type ArtifactType int
const (
// KernelModule is any kind of kernel module
KernelModule ArtifactType = iota
// KernelExploit is the privilege escalation exploit
KernelExploit
// Script for information gathering or automation
Script
)
func (at ArtifactType) String() string {
return [...]string{"module", "exploit", "script"}[at]
}
// UnmarshalTOML is for support github.com/naoina/toml
func (at *ArtifactType) UnmarshalTOML(data []byte) (err error) {
stype := strings.Trim(string(data), `"`)
stypelower := strings.ToLower(stype)
if strings.Contains(stypelower, "module") {
*at = KernelModule
} else if strings.Contains(stypelower, "exploit") {
*at = KernelExploit
} else if strings.Contains(stypelower, "script") {
*at = Script
} else {
err = fmt.Errorf("Type %s is unsupported", stype)
}
return
}
// MarshalTOML is for support github.com/naoina/toml
func (at ArtifactType) MarshalTOML() (data []byte, err error) {
s := ""
switch at {
case KernelModule:
s = "module"
case KernelExploit:
s = "exploit"
case Script:
s = "script"
default:
err = fmt.Errorf("Cannot marshal %d", at)
}
data = []byte(`"` + s + `"`)
return
}
// Duration type with toml unmarshalling support
type Duration struct {
time.Duration
}
// UnmarshalTOML for Duration
func (d *Duration) UnmarshalTOML(data []byte) (err error) {
duration := strings.Replace(string(data), "\"", "", -1)
d.Duration, err = time.ParseDuration(duration)
return
}
// MarshalTOML for Duration
func (d Duration) MarshalTOML() (data []byte, err error) {
data = []byte(`"` + d.Duration.String() + `"`)
return
}
type PreloadModule struct {
Repo string
Path string
TimeoutAfterLoad Duration
}
// Extra test files to copy over
type FileTransfer struct {
User string
Local string
Remote string
}
type Patch struct {
Path string
Source string
Script string
}
// Artifact is for .out-of-tree.toml
type Artifact struct {
Name string
Type ArtifactType
TestFiles []FileTransfer
SourcePath string
Targets []Target
Script string
Qemu struct {
Cpus int
Memory int
Timeout Duration
}
Docker struct {
Timeout Duration
}
Mitigations struct {
DisableSmep bool
DisableSmap bool
DisableKaslr bool
DisableKpti bool
}
Patches []Patch
Make struct {
Target string
}
StandardModules bool
Preload []PreloadModule
}
func (ka Artifact) checkSupport(ki distro.KernelInfo, target Target) (
supported bool, err error) {
if target.Distro.Release == "" {
if ki.Distro.ID != target.Distro.ID {
return
}
} else {
if !ki.Distro.Equal(target.Distro) {
return
}
}
r, err := regexp.Compile(target.Kernel.Regex)
if err != nil {
return
}
exr, err := regexp.Compile(target.Kernel.ExcludeRegex)
if err != nil {
return
}
if !r.MatchString(ki.KernelRelease) {
return
}
if target.Kernel.ExcludeRegex != "" && exr.MatchString(ki.KernelRelease) {
return
}
supported = true
return
}
// Supported returns true if given kernel is supported by artifact
func (ka Artifact) Supported(ki distro.KernelInfo) (supported bool, err error) {
for _, km := range ka.Targets {
supported, err = ka.checkSupport(ki, km)
if supported {
break
}
}
return
}
// KernelConfig is the ~/.out-of-tree/kernels.toml configuration description
type KernelConfig struct {
Kernels []distro.KernelInfo
@ -225,7 +25,7 @@ func readFileAll(path string) (buf []byte, err error) {
}
defer f.Close()
buf, err = ioutil.ReadAll(f)
buf, err = io.ReadAll(f)
return
}
@ -243,14 +43,3 @@ func ReadKernelConfig(path string) (kernelCfg KernelConfig, err error) {
return
}
// ReadArtifactConfig is for read .out-of-tree.toml
func ReadArtifactConfig(path string) (ka Artifact, err error) {
buf, err := readFileAll(path)
if err != nil {
return
}
err = toml.Unmarshal(buf, &ka)
return
}

View File

@ -1,40 +0,0 @@
// Copyright 2018 Mikhail Klementev. All rights reserved.
// Use of this source code is governed by a AGPLv3 license
// (or later) that can be found in the LICENSE file.
package config
import (
"testing"
"code.dumpstack.io/tools/out-of-tree/distro"
"github.com/naoina/toml"
)
func TestMarshalUnmarshal(t *testing.T) {
artifactCfg := Artifact{
Name: "Put name here",
Type: KernelModule,
}
artifactCfg.Targets = append(artifactCfg.Targets,
Target{
Distro: distro.Distro{
ID: distro.Ubuntu,
Release: "18.04",
},
Kernel: Kernel{
Regex: ".*",
},
})
buf, err := toml.Marshal(&artifactCfg)
if err != nil {
t.Fatal(err)
}
var artifactCfgNew Artifact
err = toml.Unmarshal(buf, &artifactCfgNew)
if err != nil {
t.Fatal(err)
}
}

View File

@ -1,4 +1,4 @@
package config
package dotfiles
import (
"os"

View File

@ -1,7 +1,6 @@
package config
package dotfiles
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
@ -18,7 +17,7 @@ func TestDirectory(t *testing.T) {
}
func TestDir(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "out-of-tree_")
tmpdir, err := os.MkdirTemp("", "out-of-tree_")
if err != nil {
return
}
@ -64,7 +63,7 @@ func TestDir(t *testing.T) {
}
func TestFile(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "out-of-tree_")
tmpdir, err := os.MkdirTemp("", "out-of-tree_")
if err != nil {
return
}

View File

@ -9,6 +9,8 @@ import (
"os"
"time"
"code.dumpstack.io/tools/out-of-tree/artifact"
"code.dumpstack.io/tools/out-of-tree/config/dotfiles"
"code.dumpstack.io/tools/out-of-tree/distro"
"github.com/alecthomas/kong"
@ -16,11 +18,6 @@ import (
"github.com/naoina/toml"
)
type DockerCommand struct {
Distro distro.Distro
Command string
}
type OutOfTree struct {
// Directory for all files if not explicitly specified
Directory string
@ -31,16 +28,16 @@ type OutOfTree struct {
Database string
Qemu struct {
Timeout Duration
Timeout artifact.Duration
}
Docker struct {
Timeout Duration
Timeout artifact.Duration
Registry string
// Commands that will be executed before
// the base layer of Dockerfile
Commands []DockerCommand
Commands []distro.Command
}
}
@ -82,21 +79,21 @@ func ReadOutOfTreeConf(path string) (c OutOfTree, err error) {
}
if c.Directory != "" {
Directory = c.Directory
dotfiles.Directory = c.Directory
} else {
c.Directory = Dir("")
c.Directory = dotfiles.Dir("")
}
if c.Kernels == "" {
c.Kernels = File("kernels.toml")
c.Kernels = dotfiles.File("kernels.toml")
}
if c.UserKernels == "" {
c.UserKernels = File("kernels.user.toml")
c.UserKernels = dotfiles.File("kernels.user.toml")
}
if c.Database == "" {
c.Database = File("db.sqlite")
c.Database = dotfiles.File("db.sqlite")
}
if c.Qemu.Timeout.Duration == 0 {