Author: Adam <git@apiote.tk>
run as daemon
agent.go | 176 +++++++++++++++++++++++++++++++++++++++++++-------------- go.mod | 6 + go.sum | 4 +
diff --git a/agent.go b/agent.go index 8242efa6497990adf1c5d5a95a64ed66a241ad88..6b2e0454fe9e38d21ae4ccc9d48f451f83d22a3b 100644 --- a/agent.go +++ b/agent.go @@ -7,22 +7,37 @@ "os" "os/signal" "os/user" "strconv" + "strings" "syscall" "time" "git.sr.ht/~sircmpwn/go-bare" + "github.com/sevlyar/go-daemon" ) // todo memguard var PASSWORD = "" -func socket() (string, error) { +func getUser() (*user.User, error) { u, err := user.Current() if err != nil { log.Println("error getting user", err) - return "", err + return nil, err } - return "/tmp/eeze-agent-" + u.Username, nil + return u, nil +} + +func getUserByName(username string) (*user.User, error) { + u, err := user.Lookup(username) + if err != nil { + log.Println("error getting user", err) + return nil, err + } + return u, nil +} + +func socketName(u string) string { + return "/tmp/eeze-agent-" + u } func timeOut(timeout int, sigc chan os.Signal) { @@ -38,70 +53,141 @@ os.Exit(0) } func handle(conn net.Conn) error { - for { - r := bare.NewReader(conn) - cmd, err := r.ReadU8() + r := bare.NewReader(conn) + cmd, err := r.ReadU8() + if err != nil { + log.Println("error reading command", err) + return err + } + switch cmd { + case 0: + // todo memguard + password, err := r.ReadString() if err != nil { - log.Println("error reading command", err) + log.Println("error reading password to store", err) return err } - switch cmd { - case 0: - // todo memguard - password, err := r.ReadString() - if err != nil { - log.Println("error reading password to store", err) - return err - } - PASSWORD = password - case 1: - w := bare.NewWriter(conn) - err = w.WriteString(PASSWORD) - if err != nil { - log.Println("error giving password", err) - return err - } + PASSWORD = password + case 1: + w := bare.NewWriter(conn) + err = w.WriteString(PASSWORD) + if err != nil { + log.Println("error giving password", err) + return err } + default: + return nil } + return nil +} + +func parseTimeout(timeout string) int { + i, err := strconv.ParseInt(timeout, 10, 64) + if err != nil { + log.Println("error parsing timeout, defualting to 300s", err) + } else if i < 0 { + log.Println("timeout cannot be < 0, defualting to 300s", err) + } else { + return int(i) + } + return 300 } func main() { + log.Println("main") timeout := 300 - if len(os.Args) > 1 { - i, err := strconv.ParseInt(os.Args[1], 10, 64) - if err != nil { - log.Println("error parsing timeout, defualting to 300s", err) - } else if i < 0 { - log.Println("timeout cannot be < 0, defualting to 300s", err) + skipArg := true + user, err := getUser() + if err != nil { + log.Println("error getting user name", err) + return + } + for i, arg := range os.Args { + if skipArg { + skipArg = false + continue + } + if arg == "-u" { + u, err := getUserByName(os.Args[i+1]) + if err != nil { + log.Println("error getting user from name", err) + } else { + user = u + } + skipArg = true } else { - timeout = int(i) + timeout = parseTimeout(arg) } } - socket, err := socket() + log.Println("read args ", timeout) + socket := socketName(user.Username) + log.Println("socket name ", socket) + + uid, err := strconv.ParseInt(user.Uid, 10, 64) if err != nil { + log.Println("error parsing uid", err) return } - sigc := make(chan os.Signal, 1) - signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) - go catch(sigc, socket) - if timeout > 0 { - go timeOut(timeout, sigc) + gid, err := strconv.ParseInt(user.Gid, 10, 64) + if err != nil { + log.Println("error parsing gid", err) + return } - - os.Remove(socket) - server, err := net.Listen("unix", socket) + context := new(daemon.Context) + context.LogFileName = socket + ".ctx.log" + log.Println("ctx ", context) + child, err := context.Reborn() if err != nil { - log.Println("error listening", err) + log.Println("error forking", err) return } - os.Chmod(socket, 0600) + log.Println("reborn") - for { - conn, err := server.Accept() + if child != nil { + log.Println("waiting for socket") + i := 10000 + for true { + _, err := os.Stat(socket) + if err == nil || !strings.Contains(err.Error(), "no such file or directory") { + os.Chown(socket, int(uid), int(gid)) + os.Chmod(socket, 0600) + os.Chmod(context.LogFileName, 0644) + log.Println("chmoded socket") + break + } + i-- + } + log.Println("socket exists") + return + } else { + defer context.Release() + sigc := make(chan os.Signal, 1) + log.Println("made channel") + signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) + log.Println("setup signal") + go catch(sigc, socket) + log.Println("ran catch") + if timeout > 0 { + go timeOut(timeout, sigc) + log.Println("ran timeout") + } + + server, err := net.Listen("unix", socket) if err != nil { - log.Println("error accepting", err) + log.Println("error listening", err) return } - go handle(conn) + log.Println("listening") + + log.Println("accepting") + for { + conn, err := server.Accept() + if err != nil { + log.Println("error accepting", err) + return + } + go handle(conn) + } } + } diff --git a/go.mod b/go.mod index 731857ea9b34a622122fe940ebd9e2cf1c9338d7..ee89fea90eb93ff58a56df3399c541c712d5d302 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,8 @@ module notabug.org/apiote/next-eeze-agent go 1.15 -require git.sr.ht/~sircmpwn/go-bare v0.0.0-20200812160916-d2c72e1a5018 +require ( + git.sr.ht/~sircmpwn/go-bare v0.0.0-20200812160916-d2c72e1a5018 + github.com/sevlyar/go-daemon v0.1.5 + golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect +) diff --git a/go.sum b/go.sum index 2e1ebc6c1870af5f3b87a0962b0841ac5290ad49..28d8546556844078708c1e263d3d01dcdc0109d6 100644 --- a/go.sum +++ b/go.sum @@ -3,8 +3,12 @@ git.sr.ht/~sircmpwn/go-bare v0.0.0-20200812160916-d2c72e1a5018 h1:89QMorzx6ML69PKPoayL3HuSfb7WqAlxD1dZ7DyzD0k= git.sr.ht/~sircmpwn/go-bare v0.0.0-20200812160916-d2c72e1a5018/go.mod h1:BVJwbDfVjCjoFiKrhkei6NdGcZYpkDkdyCdg1ukytRA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sevlyar/go-daemon v0.1.5 h1:Zy/6jLbM8CfqJ4x4RPr7MJlSKt90f00kNM1D401C+Qk= +github.com/sevlyar/go-daemon v0.1.5/go.mod h1:6dJpPatBT9eUwM5VCw9Bt6CdX9Tk6UWvhW3MebLDRKE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=