diff options
author | EuAndreh <eu@euandre.org> | 2024-07-22 08:35:22 -0300 |
---|---|---|
committer | EuAndreh <eu@euandre.org> | 2024-07-22 10:13:34 -0300 |
commit | 31fe7be099fb8f463be3a3db4a4b799501f66571 (patch) | |
tree | cd4d834292eba0aefbf74d0de5797b9e3fd99962 /src/lib.go | |
parent | Initial empty commit (diff) | |
download | binder-31fe7be099fb8f463be3a3db4a4b799501f66571.tar.gz binder-31fe7be099fb8f463be3a3db4a4b799501f66571.tar.xz |
v0 Impl
Diffstat (limited to 'src/lib.go')
-rw-r--r-- | src/lib.go | 132 |
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) +} |