next-eeze-agent.git

commit 6a606ba06a66cc2c03482acdb58030179e597454

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=