Compare commits

...

6 commits

Author SHA1 Message Date
b2f6d0d478 use latest sys 2024-08-19 20:37:21 +02:00
77230f5240 update dependencies 2022-10-08 16:59:34 +02:00
3e528ceb3f unveil bugfix 2018-10-26 17:02:28 +02:00
ec32483e7f fixed typo 2018-10-26 16:54:12 +02:00
089d8d16c8 added pledge and unveil support 2018-10-26 16:52:08 +02:00
23731a3702 bugfix 2018-09-20 00:14:13 +02:00
11 changed files with 144 additions and 22 deletions

View file

@ -1,4 +1,4 @@
Copyright (C) 2017 Marius Schellenberger Copyright (C) 2022 Marius Schellenberger
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without

View file

@ -1,5 +1,5 @@
# godrop - drop privileges # godrop - drop privileges
Godrop is a simple library to drop privileges on linux maschines. Godrop is a simple library to drop privileges on Linux and OpenBSD.
See the examples directory on how to use the `Drop` and `MultiDrop` functions. See the examples directory on how to use the `Drop` and `MultiDrop` functions.

4
go.mod
View file

@ -1 +1,5 @@
module git.giftfish.de/ston1th/godrop/v2 module git.giftfish.de/ston1th/godrop/v2
go 1.19
require golang.org/x/sys v0.24.0

2
go.sum Normal file
View file

@ -0,0 +1,2 @@
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

View file

@ -1,22 +1,21 @@
// Copyright (C) 2018 Marius Schellenberger // Copyright (C) 2022 Marius Schellenberger
//go:build go1.11
// +build go1.11 // +build go1.11
// Package godrop provides a simple privileges dropping library // Package godrop provides a simple library to drop privileges on Linux and OpenBSD.
package godrop package godrop
import ( import (
"errors"
"fmt" "fmt"
"net" "net"
"os" "os"
"os/exec" "os/exec"
"os/signal"
"syscall" "syscall"
) )
func errf(i interface{}) error {
return fmt.Errorf("godrop: %s", i)
}
// Config represents the drop config // Config represents the drop config
type Config struct { type Config struct {
// User is the user to drop privileges to. // User is the user to drop privileges to.
@ -42,21 +41,21 @@ func Drop(c Config, f func() (net.Listener, error)) error {
func MultiDrop(c Config, f func() ([]net.Listener, error)) error { func MultiDrop(c Config, f func() ([]net.Listener, error)) error {
uid, err := userID(c.User) uid, err := userID(c.User)
if err != nil { if err != nil {
return errf(err) return errors.New("godrop: " + err.Error())
} }
if uid == 0 { if uid == 0 {
return errf("unable to drop privileges to uid 0 (root)") return fmt.Errorf("godrop: you can't drop privileges to uid 0 (%s)", c.User)
} }
gid, err := groupID(c.Group) gid, err := groupID(c.Group)
if err != nil { if err != nil {
return errf(err) return errors.New("godrop: " + err.Error())
} }
switch os.Getuid() { switch os.Getuid() {
case 0: case 0:
cmd := exec.Command(os.Args[0], os.Args[1:]...) cmd := exec.Command(os.Args[0], os.Args[1:]...)
ln, err := f() ln, err := f()
if err != nil { if err != nil {
return errf(err) return errors.New("godrop: " + err.Error())
} }
for i, v := range ln { for i, v := range ln {
var f *os.File var f *os.File
@ -68,10 +67,10 @@ func MultiDrop(c Config, f func() ([]net.Listener, error)) error {
f, err = l.File() f, err = l.File()
l.Close() l.Close()
default: default:
return errf(fmt.Sprintf("index %d listener is not type of either *net.TCPListener or *net.UnixListener", i)) return fmt.Errorf("godrop: index %d listener is not type of either *net.TCPListener or *net.UnixListener", i)
} }
if err != nil { if err != nil {
return errf(fmt.Sprintf("index %d %s", i, err)) return fmt.Errorf("godrop: index %d %s", i, err)
} }
cmd.ExtraFiles = append(cmd.ExtraFiles, f) cmd.ExtraFiles = append(cmd.ExtraFiles, f)
} }
@ -86,19 +85,31 @@ func MultiDrop(c Config, f func() ([]net.Listener, error)) error {
} }
if c.Foreground { if c.Foreground {
cmd.SysProcAttr.Setctty = true
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
} else {
cmd.SysProcAttr.Noctty = true
} }
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
return errf(err) return errors.New("godrop: " + err.Error())
} }
if c.Foreground { if c.Foreground {
go func() {
term := make(chan os.Signal)
signal.Notify(term, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
sigs := make(chan os.Signal)
signal.Notify(sigs, syscall.SIGSTOP, syscall.SIGCONT, syscall.SIGUSR1, syscall.SIGUSR2)
for {
select {
case sig := <-term:
cmd.Process.Signal(sig)
return
case sig := <-sigs:
cmd.Process.Signal(sig)
}
}
}()
_ = cmd.Wait() _ = cmd.Wait()
os.Exit(int(cmd.ProcessState.Sys().(syscall.WaitStatus))) os.Exit(int(cmd.ProcessState.Sys().(syscall.WaitStatus)))
} }
@ -107,7 +118,7 @@ func MultiDrop(c Config, f func() ([]net.Listener, error)) error {
case uid: case uid:
return nil return nil
} }
return errf("dropping priviledges failed") return errors.New("godrop: dropping priviledges failed")
} }
// GetListener returns the listener socket of file descriptor 3 // GetListener returns the listener socket of file descriptor 3
@ -118,7 +129,7 @@ func GetListener() (net.Listener, error) {
// GetListenerFd returns the listener socket of the given file descriptor // GetListenerFd returns the listener socket of the given file descriptor
func GetListenerFd(fd int) (net.Listener, error) { func GetListenerFd(fd int) (net.Listener, error) {
if fd < 3 { if fd < 3 {
return nil, errf("fd is less than 3") return nil, errors.New("godrop: fd is less than 3")
} }
f := os.NewFile(uintptr(fd), "") f := os.NewFile(uintptr(fd), "")
defer f.Close() defer f.Close()

View file

@ -1,5 +1,6 @@
// Copyright (C) 2018 Marius Schellenberger // Copyright (C) 2022 Marius Schellenberger
//go:build go1.11
// +build go1.11 // +build go1.11
package godrop package godrop

View file

@ -1,4 +1,4 @@
// Copyright (C) 2018 Marius Schellenberger // Copyright (C) 2022 Marius Schellenberger
package godrop package godrop

15
pledge.go Normal file
View file

@ -0,0 +1,15 @@
// Copyright (C) 2022 Marius Schellenberger
//go:build !openbsd
// +build !openbsd
package godrop
// Pledge is currently only supported on OpenBSD.
func Pledge(promises, execpromises string) error { return nil }
// PledgePromises is currently only supported on OpenBSD.
func PledgePromises(promises string) error { return nil }
// PledgeExecPromises is currently only supported on OpenBSD.
func PledgeExecpromises(execpromises string) error { return nil }

44
pledge_openbsd.go Normal file
View file

@ -0,0 +1,44 @@
// Copyright (C) 2022 Marius Schellenberger
//go:build openbsd
// +build openbsd
package godrop
import (
"errors"
"golang.org/x/sys/unix"
)
// Pledge is a wrapper for x/sys/unix Pledge.
//
// See https://go.googlesource.com/sys/+/master/unix/openbsd_pledge.go for usage.
func Pledge(promises, execpromises string) (err error) {
err = unix.Pledge(promises, execpromises)
if err != nil {
err = errors.New("pledge: " + err.Error())
}
return
}
// PledgePromises is a wrapper for x/sys/unix PledgePromises.
//
// See https://go.googlesource.com/sys/+/master/unix/openbsd_pledge.go for usage.
func PledgePromises(promises string) (err error) {
err = unix.PledgePromises(promises)
if err != nil {
err = errors.New("pledge: " + err.Error())
}
return
}
// PledgeExecpromises is a wrapper for x/sys/unix PledgeExecpromises.
//
// See https://go.googlesource.com/sys/+/master/unix/openbsd_pledge.go for usage.
func PledgeExecpromises(execpromises string) (err error) {
err = unix.PledgeExecpromises(execpromises)
if err != nil {
err = errors.New("pledge: " + err.Error())
}
return
}

12
unveil.go Normal file
View file

@ -0,0 +1,12 @@
// Copyright (C) 2022 Marius Schellenberger
//go:build !openbsd
// +build !openbsd
package godrop
// Unveil is currently only supported on OpenBSD.
func Unveil(path, flags string) error { return nil }
// UnveilBlock is currently only supported on OpenBSD.
func UnveilBlock() error { return nil }

33
unveil_openbsd.go Normal file
View file

@ -0,0 +1,33 @@
// Copyright (C) 2022 Marius Schellenberger
//go:build openbsd
// +build openbsd
package godrop
import (
"errors"
"golang.org/x/sys/unix"
)
// Unveil is a wrapper for x/sys/unix Unveil.
//
// See https://go.googlesource.com/sys/+/master/unix/openbsd_unveil.go for usage.
func Unveil(path, flags string) (err error) {
err = unix.Unveil(path, flags)
if err != nil {
err = errors.New("unveil: " + err.Error())
}
return
}
// UnveilBlock is a wrapper for x/sys/unix UnveilBlock.
//
// See https://go.googlesource.com/sys/+/master/unix/openbsd_unveil.go for usage.
func UnveilBlock() (err error) {
err = unix.UnveilBlock()
if err != nil {
err = errors.New("unveil: " + err.Error())
}
return
}