diff --git a/experimental/boxdd/authorize_takeover_linux.go b/experimental/boxdd/authorize_linux.go similarity index 62% rename from experimental/boxdd/authorize_takeover_linux.go rename to experimental/boxdd/authorize_linux.go index 8fd1912c..9cdf0430 100644 --- a/experimental/boxdd/authorize_takeover_linux.go +++ b/experimental/boxdd/authorize_linux.go @@ -7,6 +7,7 @@ import ( "crypto/rand" "encoding/hex" "math" + "os" "strconv" E "github.com/sagernet/sing/common/exceptions" @@ -17,11 +18,12 @@ import ( ) const ( - policyKitService = "org.freedesktop.PolicyKit1" - policyKitAuthorityPath = dbus.ObjectPath("/org/freedesktop/PolicyKit1/Authority") - policyKitAuthorityInterface = "org.freedesktop.PolicyKit1.Authority" - policyKitTakeOverAction = "io.nekohasekai.sfl.take-over-service" - policyKitAllowUserInteraction = uint32(1) + policyKitService = "org.freedesktop.PolicyKit1" + policyKitAuthorityPath = dbus.ObjectPath("/org/freedesktop/PolicyKit1/Authority") + policyKitAuthorityInterface = "org.freedesktop.PolicyKit1.Authority" + policyKitTakeOverAction = "io.nekohasekai.sfl.take-over-service" + policyKitSetInsecureModeAction = "io.nekohasekai.sfl.set-insecure-mode" + policyKitAllowUserInteraction = uint32(1) ) type policyKitSubject struct { @@ -36,6 +38,27 @@ type policyKitAuthorizationResult struct { } func authorizeTakeOver(ctx context.Context, identity peerIdentity) error { + return checkPolicyKitAuthorization(ctx, identity, policyKitTakeOverAction) +} + +func authorizeSetInsecureMode(ctx context.Context, identity peerIdentity, enabled bool) error { + if enabled { + return checkPolicyKitAuthorization(ctx, identity, policyKitSetInsecureModeAction) + } + ownerUserID, err := loadOwner() + if err != nil { + if os.IsNotExist(err) { + return status.Error(codes.PermissionDenied, "the service has no owner") + } + return err + } + if ownerUserID != identity.UserID { + return status.Error(codes.PermissionDenied, "the service is owned by another user") + } + return nil +} + +func checkPolicyKitAuthorization(ctx context.Context, identity peerIdentity, action string) error { if listenAddress != "" { return nil } @@ -72,7 +95,7 @@ func authorizeTakeOver(ctx context.Context, identity peerIdentity) error { 0, resultChannel, subject, - policyKitTakeOverAction, + action, map[string]string{}, policyKitAllowUserInteraction, cancellationID, @@ -88,7 +111,10 @@ func authorizeTakeOver(ctx context.Context, identity peerIdentity) error { return E.Cause(err, "read PolicyKit authorization result") } if !result.Authorized { - return status.Error(codes.PermissionDenied, "take over authorization was denied") + if result.Challenge { + return status.Error(codes.Unauthenticated, "no authentication agent is available") + } + return status.Error(codes.PermissionDenied, "authorization was denied") } return nil case <-ctx.Done(): @@ -97,6 +123,6 @@ func authorizeTakeOver(ctx context.Context, identity peerIdentity) error { 0, cancellationID, ).Err - return status.Error(codes.Canceled, "take over authorization was canceled") + return status.Error(codes.Canceled, "authorization was canceled") } } diff --git a/experimental/boxdd/authorize_stub.go b/experimental/boxdd/authorize_stub.go new file mode 100644 index 00000000..7c4cf241 --- /dev/null +++ b/experimental/boxdd/authorize_stub.go @@ -0,0 +1,21 @@ +//go:build !linux + +package main + +import ( + "context" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func authorizeTakeOver(ctx context.Context, identity peerIdentity) error { + return nil +} + +func authorizeSetInsecureMode(ctx context.Context, identity peerIdentity, enabled bool) error { + if enabled { + return status.Error(codes.PermissionDenied, "enabling insecure mode requires an elevated service command") + } + return nil +} diff --git a/experimental/boxdd/authorize_takeover_stub.go b/experimental/boxdd/authorize_takeover_stub.go deleted file mode 100644 index c62b68d5..00000000 --- a/experimental/boxdd/authorize_takeover_stub.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !linux - -package main - -import "context" - -func authorizeTakeOver(ctx context.Context, identity peerIdentity) error { - return nil -} diff --git a/experimental/boxdd/desktop_service.go b/experimental/boxdd/desktop_service.go index e9422fec..1942f9fb 100644 --- a/experimental/boxdd/desktop_service.go +++ b/experimental/boxdd/desktop_service.go @@ -247,26 +247,23 @@ func (s *desktopService) SetInsecureModeEnabled(ctx context.Context, request *Se if !insecureModeAvailable() { return nil, status.Error(codes.FailedPrecondition, "insecure mode is not available on this platform") } - if request.Enabled { - return nil, status.Error(codes.PermissionDenied, "enabling insecure mode requires an elevated service command") + err = authorizeSetInsecureMode(ctx, identity, request.Enabled) + if err != nil { + return nil, err } s.daemon.lifecycleAccess.Lock() defer s.daemon.lifecycleAccess.Unlock() if s.daemon.closed { return nil, os.ErrClosed } - err = authorizeDisableInsecureMode(identity) - if err != nil { - return nil, err - } wasEnabled := s.daemon.insecureModeEnabled() err = updateDaemonSettings(workingDirectory, func(settings *daemonSettings) { - settings.InsecureModeEnabled = false + settings.InsecureModeEnabled = request.Enabled }) if err != nil { return nil, err } - if wasEnabled && s.daemon.startedService.Instance() != nil { + if wasEnabled && !request.Enabled && s.daemon.startedService.Instance() != nil { var ownerUserID string ownerUserID, err = loadOwner() if err != nil { diff --git a/experimental/boxdd/insecure_mode_authorize_linux.go b/experimental/boxdd/insecure_mode_authorize_linux.go deleted file mode 100644 index 35769a0c..00000000 --- a/experimental/boxdd/insecure_mode_authorize_linux.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build linux - -package main - -import ( - "os" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -func authorizeDisableInsecureMode(identity peerIdentity) error { - ownerUserID, err := loadOwner() - if err != nil { - if os.IsNotExist(err) { - return status.Error(codes.PermissionDenied, "the service has no owner") - } - return err - } - if ownerUserID != identity.UserID { - return status.Error(codes.PermissionDenied, "the service is owned by another user") - } - return nil -} diff --git a/experimental/boxdd/insecure_mode_authorize_stub.go b/experimental/boxdd/insecure_mode_authorize_stub.go deleted file mode 100644 index 8040cbea..00000000 --- a/experimental/boxdd/insecure_mode_authorize_stub.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build !linux - -package main - -func authorizeDisableInsecureMode(identity peerIdentity) error { - return nil -}