summaryrefslogtreecommitdiff
path: root/src/lib.go
diff options
context:
space:
mode:
authorEuAndreh <eu@euandre.org>2024-07-22 08:35:22 -0300
committerEuAndreh <eu@euandre.org>2024-07-22 10:13:34 -0300
commit31fe7be099fb8f463be3a3db4a4b799501f66571 (patch)
treecd4d834292eba0aefbf74d0de5797b9e3fd99962 /src/lib.go
parentInitial empty commit (diff)
downloadbinder-31fe7be099fb8f463be3a3db4a4b799501f66571.tar.gz
binder-31fe7be099fb8f463be3a3db4a4b799501f66571.tar.xz
v0 Impl
Diffstat (limited to 'src/lib.go')
-rw-r--r--src/lib.go132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/lib.go b/src/lib.go
new file mode 100644
index 0000000..04ac41e
--- /dev/null
+++ b/src/lib.go
@@ -0,0 +1,132 @@
+package binder
+
+import (
+ "fmt"
+ "io"
+ "net"
+ "os"
+ "os/user"
+ "strconv"
+ "syscall"
+
+ g "euandre.org/gobang/src"
+)
+
+
+
+type CLIArgs struct {
+ FromAddr string
+ ToAddr string
+}
+
+
+
+const USER = "nobody"
+
+
+
+var EmitActiveConnection = g.MakeGauge("active-connections")
+
+
+
+func dropPrivileges(username string) {
+ g.Info("Dropping privileges", "drop-root-init")
+
+ user, err := user.Lookup(username)
+ g.FatalIf(err)
+
+ gid, err := strconv.Atoi(user.Gid)
+ g.FatalIf(err)
+
+ uid, err := strconv.Atoi(user.Uid)
+ g.FatalIf(err)
+
+ err = syscall.Setgid(gid)
+ g.FatalIf(err)
+
+ err = syscall.Setgroups([]int{})
+ g.FatalIf(err)
+
+ err = syscall.Setuid(uid)
+ g.FatalIf(err)
+
+ g.Info("Privileges dropped", "drop-root-end")
+}
+
+func isRunningAsRoot() bool {
+ return os.Geteuid() == 0
+}
+
+func copyData(closer chan struct{}, from io.Reader, to io.Writer) {
+ io.Copy(to, from)
+ closer <- struct{}{}
+}
+
+func ParseArgs(args []string) CLIArgs {
+ if len(args) != 3 {
+ fmt.Fprintf(
+ os.Stderr,
+ "Usage: %s FROM-ADDRESS TO-ADDRESS\n",
+ args[0],
+ )
+ os.Exit(2)
+ }
+ return CLIArgs {
+ FromAddr: args[1],
+ ToAddr: args[2],
+ }
+}
+
+func DropRoot() {
+ if isRunningAsRoot() {
+ dropPrivileges(USER)
+ if isRunningAsRoot() {
+ panic("Failed to drop privileges")
+ }
+ }
+}
+
+func Start(toAddr string, listener net.Listener) {
+ for {
+ connFrom, err := listener.Accept()
+ if err != nil {
+ g.Warning(
+ "Error accepting connection",
+ "accept-connection",
+ "err", err,
+ )
+ continue
+ }
+ defer connFrom.Close()
+ EmitActiveConnection.Inc()
+
+ connTo, err := net.Dial("unix", toAddr)
+ if err != nil {
+ g.Error(
+ "Error dialing connection",
+ "dial-connection",
+ "err", err,
+ )
+ return
+ }
+ defer connTo.Close()
+
+ closer := make(chan struct{}, 2)
+ go copyData(closer, connFrom, connTo)
+ go copyData(closer, connTo, connFrom)
+ go func() {
+ <-closer
+ EmitActiveConnection.Dec()
+ }()
+ }
+}
+
+
+func Main() {
+ args := ParseArgs(os.Args)
+ listener, err := net.Listen("tcp", args.FromAddr)
+ g.FatalIf(err)
+
+ DropRoot()
+ Start(args.ToAddr, listener)
+}