aghnet: imp permissions logic

This commit is contained in:
Eugene Burkov 2023-02-06 16:11:55 +03:00
parent da1b53a3b4
commit 3918789ca7
5 changed files with 41 additions and 6 deletions

View file

@ -80,6 +80,11 @@ func CanBindPrivilegedPorts() (can bool, err error) {
return canBindPrivilegedPorts() return canBindPrivilegedPorts()
} }
// AcquirePermissions tries to acquire permissions to bind to privileged ports.
func AcquirePermissions() (err error) {
return acquirePermissions()
}
// NetInterface represents an entry of network interfaces map. // NetInterface represents an entry of network interfaces map.
type NetInterface struct { type NetInterface struct {
// Addresses are the network interface addresses. // Addresses are the network interface addresses.

View file

@ -7,3 +7,7 @@ import "github.com/AdguardTeam/AdGuardHome/internal/aghos"
func canBindPrivilegedPorts() (can bool, err error) { func canBindPrivilegedPorts() (can bool, err error) {
return aghos.HaveAdminRights() return aghos.HaveAdminRights()
} }
func acquirePermissions() (err error) {
return nil
}

View file

@ -23,17 +23,17 @@ const dhcpcdConf = "etc/dhcpcd.conf"
func canBindPrivilegedPorts() (can bool, err error) { func canBindPrivilegedPorts() (can bool, err error) {
res, err := unix.PrctlRetInt( res, err := unix.PrctlRetInt(
unix.PR_CAP_AMBIENT, unix.PR_CAPBSET_READ,
unix.PR_CAP_AMBIENT_RAISE,
unix.CAP_NET_BIND_SERVICE, unix.CAP_NET_BIND_SERVICE,
0, 0,
0, 0,
0,
) )
if err != nil { if err != nil {
if errors.Is(err, unix.EINVAL) { if errors.Is(err, unix.EINVAL) {
// Older versions of Linux kernel do not support this. Print a // Older versions of Linux kernel do not support this. Print a
// warning and check admin rights. // warning and check admin rights.
log.Info("warning: cannot check capability cap_net_bind_service: %s", err) log.Info("warning: cannot check cap_net_bind_service: %s", err)
} else { } else {
return false, err return false, err
} }
@ -45,6 +45,21 @@ func canBindPrivilegedPorts() (can bool, err error) {
return res == 1 || adm, nil return res == 1 || adm, nil
} }
func acquirePermissions() (err error) {
_, err = unix.PrctlRetInt(
unix.PR_CAP_AMBIENT,
unix.PR_CAP_AMBIENT_RAISE,
unix.CAP_NET_BIND_SERVICE,
0,
0,
)
if err != nil {
return fmt.Errorf("raising cap_net_bind_service: %w", err)
}
return nil
}
// dhcpcdStaticConfig checks if interface is configured by /etc/dhcpcd.conf to // dhcpcdStaticConfig checks if interface is configured by /etc/dhcpcd.conf to
// have a static IP. // have a static IP.
func (n interfaceName) dhcpcdStaticConfig(r io.Reader) (subsources []string, cont bool, err error) { func (n interfaceName) dhcpcdStaticConfig(r io.Reader) (subsources []string, cont bool, err error) {

View file

@ -43,3 +43,7 @@ func closePortChecker(c io.Closer) (err error) {
func isAddrInUse(err syscall.Errno) (ok bool) { func isAddrInUse(err syscall.Errno) (ok bool) {
return errors.Is(err, windows.WSAEADDRINUSE) return errors.Is(err, windows.WSAEADDRINUSE)
} }
func acquirePermissions() (err error) {
return nil
}

View file

@ -570,14 +570,21 @@ func startMods() (err error) {
func checkPermissions() { func checkPermissions() {
log.Info("Checking if AdGuard Home has necessary permissions") log.Info("Checking if AdGuard Home has necessary permissions")
if ok, err := aghnet.CanBindPrivilegedPorts(); !ok || err != nil { err := aghnet.AcquirePermissions()
log.Fatal("This is the first launch of AdGuard Home. You must run it as Administrator.") if err != nil {
log.Debug("acquiring necessary permissions: %s", err)
var ok bool
if ok, err = aghnet.CanBindPrivilegedPorts(); !ok || err != nil {
log.Fatal("This is the first launch of AdGuard Home. You must run it as Administrator.")
}
} }
// We should check if AdGuard Home is able to bind to port 53 // We should check if AdGuard Home is able to bind to port 53
err := aghnet.CheckPort("tcp", netip.AddrPortFrom(netutil.IPv4Localhost(), defaultPortDNS)) err = aghnet.CheckPort("tcp", netip.AddrPortFrom(netutil.IPv4Localhost(), defaultPortDNS))
if err != nil { if err != nil {
if errors.Is(err, os.ErrPermission) { if errors.Is(err, os.ErrPermission) {
log.Debug("checking permissions via binding: %v", err)
log.Fatal(`Permission check failed. log.Fatal(`Permission check failed.
AdGuard Home is not allowed to bind to privileged ports (for instance, port 53). AdGuard Home is not allowed to bind to privileged ports (for instance, port 53).