Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QUESTION: make lib works when run program as another user. #63

Closed
dyorgio opened this issue Sep 17, 2017 · 19 comments
Closed

QUESTION: make lib works when run program as another user. #63

dyorgio opened this issue Sep 17, 2017 · 19 comments

Comments

@dyorgio
Copy link

dyorgio commented Sep 17, 2017

I'm trying to start my program with root to another users on machine.

I already tried "runuser"(-l and -u) and "su username", but no way to make it works.

The best try, for now was:

sudo runuser -l username -c "DISPLAY=:0 XDG_CURRENT_DESKTOP=$XDG_CURRENT_DESKTOP program-name"

The program works, without error, but no icon appears :(, somebody have any glue who to make it works?

@dyorgio
Copy link
Author

dyorgio commented Sep 17, 2017

Almost done with:

sudo su username /bin/sh -c "XDG_CURRENT_DESKTOP=$XDG_CURRENT_DESKTOP program-name"

But this warning appears:

18:29:30.061 [main] WARN dorkbox.systemTray.SystemTray - Attempting to load the SystemTray as the 'root/sudo' user. This will likely not work because of dbus restrictions. Using the Swing Tray type instead.

But process is running as my user:
captura de tela 2017-09-17 as 18 30 31

@dorkbox
Copy link
Owner

dorkbox commented Sep 17, 2017

What OS and window manager?

In most cases, because of the way dbus works, the application running must also be the same user that the desktop is running under. There are ways around it, but involve managing the dbus directly, which is far to much effort for me.

See if you can get it to work without using sudo at all, since the check for running as root is via System.getenv("SUDO_USER").

Since it's super easy to add a "root override", where all root checks are disabled I'll do that real quick. If it works, it works, if not - there's nothing I know of to make it work.

@dyorgio
Copy link
Author

dyorgio commented Sep 17, 2017

I'm testing in Ubuntu 16.04 with Unity.

Sadly it doesn't work with:

dorkbox.systemTray.SystemTray.AUTO_FIX_INCONSISTENCIES = false;

I tried only with su, but before I need to enter in a bash with sudo (same thing at the end).
:(.

My application needs a "service" that start my program on users sessions if it is not open (crashed or terminated by user), like a auto-restart (keep alive).

Can you give me some advices about manage bus directly?

@dorkbox
Copy link
Owner

dorkbox commented Sep 17, 2017

(this specifically has to do with app-indicators. I just pushed version 3.7, which has SystemTray.ENABLE_ROOT_CHECK

@dorkbox
Copy link
Owner

dorkbox commented Sep 17, 2017

I have no idea how to manage the dbus directly. My research ended when I discovered that it is not easy. However, I've tested against Ubuntu 16.04 + Unity, and the fallback "Swing" tray type worked in a VM.

@dyorgio
Copy link
Author

dyorgio commented Sep 17, 2017

Yes, I can confirm that swing is working here too :).

@dorkbox
Copy link
Owner

dorkbox commented Sep 17, 2017

Ah, good to know swing works in more than a VM. Can you try 3.7 and tell me if SystemTray.ENABLE_ROOT_CHECK=false works in your situation? All it does is disable the warning + swing fallback (since SystemTray.AUTO_FIX_INCONSISTENCIES does a lot of things, it's best to leave that true)

@dorkbox
Copy link
Owner

dorkbox commented Sep 17, 2017

As far as DBUS stuff goes, If you can get a C example running (I have some test examples in the test directory), I can probably port that to java.

@dyorgio
Copy link
Author

dyorgio commented Sep 17, 2017

I got it!

Using this command it works (with root warning):

sudo su username /bin/sh -c "DBUS_SESSION_BUS_ADDRESS='unix:abstract=/tmp/dbus-cLtEoBPmgC' XDG_CURRENT_DESKTOP=$XDG_CURRENT_DESKTOP program-name"

I get "unix:abstract=/tmp/dbus-cLtEoBPmgC" from /run/user/{uid}/dbus-session.

What do you think? it is a good start point to include into lib?

EDIT: it works without sudo(root) but my service runs as root like user.

@dorkbox
Copy link
Owner

dorkbox commented Sep 17, 2017

Awesome! Thanks for figuring it out - i'll definitely include that info.

If you want, you can disable the root warning/checks via SystemTray.ENABLE_ROOT_CHECK=false now.

@dorkbox dorkbox closed this as completed Sep 17, 2017
@dyorgio
Copy link
Author

dyorgio commented Sep 19, 2017

Example to run as user with root:

        // Get dbus-daemon PID
        Process process = Runtime.getRuntime().exec(new String[]{//
            "/bin/sh", "-c", //
            "ps aux | grep \"^" + user + " \" | grep \"dbus-daemon\" | grep \"unix:\" | awk '{print $2}'" //
        });
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String pid = reader.readLine();
        reader.close();

        // Read DBUS env values
        Map<String, String> dbusEnv = new HashMap();
        process = Runtime.getRuntime().exec(new String[]{//
            "/bin/sh", "-c", //
            "cat /proc/" + pid + "/environ | tr '\\0' '\\n'" //
        });
        
        reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;
        int splitIndex;
        while ((line = reader.readLine()) != null) {
            splitIndex = line.indexOf('=');
            if (splitIndex != -1) {
                dbusEnv.put(line.substring(0, splitIndex), line.substring(splitIndex + 1));
            }
        }
        reader.close();

        String xdgDesktop = dbusEnv.get("XDG_CURRENT_DESKTOP");
        if (xdgDesktop == null) {
            xdgDesktop = "Unity"; // Ubuntu Rules!
        }

        String display = dbusEnv.get("DISPLAY");
        if (display == null) {
            display = ":0"; // display default
        }

        String dbusAddress = dbusEnv.get("DBUS_SESSION_BUS_ADDRESS");

        process = Runtime.getRuntime().exec(new String[]{//
            "runuser", //
            user,//
            "-c",//
            "/bin/sh -c \"DISPLAY=" + display + " DBUS_SESSION_BUS_ADDRESS=" + dbusAddress + " XDG_CURRENT_DESKTOP=" + xdgDesktop + " YOUR-COMMAND\""//
        });

@dorkbox
Copy link
Owner

dorkbox commented Sep 19, 2017

Perfect! May I add this as a Utility method under Apache 2.0?

@dyorgio
Copy link
Author

dyorgio commented Sep 19, 2017

@dorkbox always :D

@tresf
Copy link

tresf commented Sep 19, 2017

@dyorgio
Copy link
Author

dyorgio commented Sep 19, 2017

@tresf, if GNOME_DESKTOP_SESSION_ID is present in dbus-daemon env vars yes, you just need to include in your version this:

dbusEnv.get("GNOME_DESKTOP_SESSION_ID");

In my Ubuntu I don't have this, only theses:

XDG_SESSION_TYPE=x11
DESKTOP_SESSION=ubuntu
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-cLtEoBPmgC
SESSIONTYPE=gnome-session
XDG_SESSION_ID=c2
XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0
XDG_SESSION_DESKTOP=ubuntu
GDMSESSION=ubuntu
DESKTOP_SESSION=ubuntu
XDG_CURRENT_DESKTOP=Unity
XDG_SESSION_DESKTOP=ubuntu

EDIT: @tresf, looking at your linked issue I think that the problem is <3.7 fallback to swing, if you use this solution and version +3.7 it will be solved.

@tresf
Copy link

tresf commented Sep 19, 2017

@dyorgio thanks. If you think you can tackle the linked stackoverflow article, we'd be willing to put a bounty on it.

@dyorgio
Copy link
Author

dyorgio commented Sep 20, 2017

@tresf Done :), please, tell us if it works or not.

@tresf
Copy link

tresf commented Nov 12, 2018

@dorkbox thanks to the help of @dyorgio, we've shimmed some logic into another project which can read environment variables for the user which is running the sudo command...

This is a bash script -- and one which makes quite a bit of assumptions -- but it seems to work rather well. Feel free to use any portions of it under whichever license you choose.

#!/bin/bash

# Provide user environmental variables to the sudo environment
function sudo_env() {
    userid="$(logname 2>/dev/null || echo $SUDO_USER)"
    pid=$(ps aux |grep "^$userid" |grep "dbus-daemon" | grep "unix:" |awk '{print $2}')
    # Replace null delimiters with newline for grep
    envt=$(cat "/proc/$pid/environ" 2> /dev/null |tr '\0' '\n')

    # List of environmental variables to use; adjust as needed
    # UPSTART_SESSION must come before GNOME_DESKTOP_SESSION_ID
    exports=( "UPSTART_SESSION" "DISPLAY" "DBUS_SESSION_BUS_ADDRESS" "XDG_CURRENT_DESKTOP" "GNOME_DESKTOP_SESSION_ID" )

    for i in "${exports[@]}"; do
        # Re-set the variable within this session by name
        # Careful, this technique won't yet work with spaces
        if echo "$envt" | grep "^$i=" > /dev/null 2>&1; then
            eval "$(echo "$envt" | grep "^$i=")" > /dev/null 2>&1
	    export $i > /dev/null 2>&1
	elif initctl --user get-env $i > /dev/null 2>&1; then
            eval "$i=$(initctl --user get-env $i)" > /dev/null 2>&1
	    export $i > /dev/null 2>&1
	fi

        echo -e "        $i=${!i}"
    done
}

sudo_env

@dyorgio
Copy link
Author

dyorgio commented Jun 14, 2019

Hi guys,

In last fedora (30) dbus-daemon was replaced (I guess) by dbus-broker-launch, but I can't make it works with SystemTray Lib, no appindicator is showing and if I pass mouse over tray area, process is killed by SIGTRAP signal....

If I run same application as user, everything works... Anybody tried to run an app that uses this lib with root as another user with success on Fedora 30?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants